用一个线程控制一个事务执行

本文介绍了一个基于Struts2和Spring框架的项目中如何实现定时任务。具体包括在web.xml中配置监听器,通过自定义类实现ServletContextListener接口并在项目启动时初始化线程,设置定时任务每天执行一次特定的操作。

1.项目启动会执行该线程,然后这个线程控制执行一个事务

1.项目用的struts2+spring   再web.xml添加监听


     <listener>
<listener-class>cn.cntomorrow.jzsh.timerThead.Handle</listener-class>
</listener>


2.


package cn.cntomorrow.jzsh.timerThead;
import java.text.ParseException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/****
 * 项目自启动程序入口
 * @author yweiwei
 */
public class Handle implements ServletContextListener,
HttpSessionListener, ServletRequestListener{
   public void contextDestroyed(ServletContextEvent arg0) {  
   }  
  /***
   * 创建监听程序:项目启动即自启动此程序
   */
   public void contextInitialized(ServletContextEvent arg0) {  
    for(int i=0;i<5;i++){
System.out.println("==============线程开始启动==================");
}
   
    TheadContrl t=new TheadContrl();
    try {
    //调用执行的方法
t.createsite();
} catch (ParseException e) {
e.printStackTrace();
}
   }  
  
   public void sessionCreated(HttpSessionEvent arg0) {  
   }  
  
   public void sessionDestroyed(HttpSessionEvent arg0) {  
   }  
  
   public void requestDestroyed(ServletRequestEvent arg0) {  
   }  
  
   public void requestInitialized(ServletRequestEvent arg0) {  
   }  

}


3.


package cn.cntomorrow.jzsh.timerThead;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import mt.framework.util.Logger;
import org.apache.commons.collections.map.ListOrderedMap;


import cn.cntomorrow.jzsh.ws.action.JzshAction;
/***
 * 线程管理类 
 * @author  yweiwei
 */
public class TheadContrl   {
private TaskDo taskdo = new TaskDo();
//创建一个线程池
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
public void createsite() throws ParseException{
// 一天的毫秒数
long daySpan = 24 * 60 * 60 * 1000;
// 规定的每天时间15:33:30运行
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd '11:00:00'");
// 首次运行时间
Date startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(sdf.format(new Date()));
// 如果今天的已经过了 首次运行时间就改为明天
if(System.currentTimeMillis() > startTime.getTime())
 startTime = new Date(startTime.getTime() + daySpan);
 Timer t = new Timer();
 TimerTask task = new TimerTask(){
 @Override
 public void run() {
  // 要执行的代码
  String sitecode="1";
           String s="2";
          Logger.info("线程:执行一次jzsh增量开始");
           try {
            /***
            * 先推送删除基站信息
            */
          List<ListOrderedMap>    rlist = taskdo.selectdeleteBaseInfo(s);//查询删除的基站  参数2作为查询删除基站的条件
          for (int i=0;i<rlist.size();i++) {
        //得到删除的基站id
String n=(String) rlist.get(i).get("BASESTATION_ID");
   JzshAction jzsh=new JzshAction();
          jzsh.createsite(n,n);//查询删除基站
  }
          //查询增加的基站
         rlist = taskdo.selectBaseInfo(sitecode);
          for (int i=0;i<rlist.size();i++) {
String m=(String) rlist.get(i).get("BASESTATION_ID");
   JzshAction jzsh=new JzshAction();
          jzsh.createsite(m);
  }
            System.gc();
               Thread.sleep(2000);
           }catch (InterruptedException e) {
               e.printStackTrace();
           }catch (Exception e){
            e.printStackTrace();
           }
           Logger.info("线程:执行一次jzsh增量结束");
 }
};
// 以每24小时执行一次
t.scheduleAtFixedRate(task, startTime, daySpan);
}

}



<think>好的,我现在需要回答用户关于如何保证一个线程原子执行的问题。首先,我得回想一下线程和原子操作的基本概念。原子操作指的是一个操作在执行过程中不可被中断,要么完全执行,要么不执行,不会出现中间状态。这在多线程环境中尤为重要,因为多个线程同时访问共享资源可能导致数据不一致的问题。 接下来,我需要确定用户可能关心的方面。用户可能想知道具体的实现方法,比如编程语言提供的机制或者同步工具。常见的保证原子执行的方法包括使用锁、原子变量、CAS操作等。我需要将这些方法逐一解释清楚,并举例说明。 首先想到的是互斥锁(Mutex)。使用锁可以确保同一时间只有一个线程访问临界区。比如在Java中,synchronized关键字或者ReentrantLock类可以实现这一点。要解释清楚锁的基本原理,以及如何正确使用,比如避免死锁,确保锁的释放等。 然后是原子变量。许多语言提供了原子类,如Java的java.util.concurrent.atomic包中的AtomicInteger。这些类通过底层的CAS(Compare-And-Swap)操作来保证原子性。需要说明CAS的工作原理,比较并交换的机制,以及它在无锁编程中的应用。 接着,可能涉及到事务内存(Transactional Memory)的概念,虽然这在某些语言中可能不常见,但也是一个高级的解决方案。不过可能用户更关注常用方法,所以这部分可以简要提及。 另外,需要提到内存屏障(Memory Barrier)或者volatile关键字,虽然volatile在某些语言中(如Java)只能保证可见性,不能保证原子性,但结合其他机制可能有用。这里要避免误导用户,明确volatile的局限性。 还要考虑不同的编程环境,比如C++中的std::atomic,或者Go中的sync/atomic包,可能用户使用的语言不同,但通用原则是相似的。需要保持回答的语言中立,或者提到不同语言中的实现方式。 可能会遗漏一些细节,比如自旋锁(Spinlock)与互斥锁的区别,或者信号量(Semaphore)的使用,但用户的问题是关于原子执行,所以重点应在原子操作和锁机制上。 需要检查是否有错误,比如是否正确区分了原子操作和临界区的保护。例如,简单的i++操作即使使用volatile也不是原子的,必须使用原子变量或同步机制。 最后,总结关键点,强调选择合适的方法取决于具体场景和性能要求。比如高并发下无锁结构可能更高效,而锁机制更简单但可能有性能开销。</think>要保证一个线程原子地执行代码,需要通过同步机制确保操作的不可分割性。以下是几种常见方法及示例: 一、互斥锁(Mutex) ```java // Java示例 private final Object lock = new Object(); private int counter = 0; public void increment() { synchronized(lock) { // 进入临界区 counter++; } // 退出临界区 } ``` - 原理:通过锁机制保证同一时刻只有一个线程执行临界区代码 - 注意:要避免嵌套锁、保证异常情况也能释放锁 二、原子变量(Atomic Variables) ```java // Java示例 AtomicInteger atomicCounter = new AtomicInteger(0); public void safeIncrement() { atomicCounter.getAndIncrement(); // 原子操作 } ``` - 底层使用CAS(Compare-And-Swap)实现: ```cpp // 伪代码示意 bool CAS(int* addr, int expected, int newValue) { if(*addr == expected){ *addr = newValue; return true; } return false; } ``` - 优势:无锁实现,适合高并发场景 三、信号量(Semaphore) ```python # Python示例 import threading sem = threading.Semaphore(1) def critical_section(): sem.acquire() # 执行原子操作 sem.release() ``` 四、内存屏障(Memory Barrier) ```cpp // C++示例 std::atomic<int> atomic_val{0}; void update() { atomic_val.store(42, std::memory_order_release); } ``` 五、事务内存(Transactional Memory) ```cpp // C++实验性特性示例 synchronized { // 原子执行的代码块 } ``` 选择策略: 1. 简单计数器 → 原子变量 2. 复杂数据操作 → 互斥锁 3. 高性能需求 → CAS无锁结构 4. 资源控制 → 信号量 注意事项: - 避免锁粒度太粗(性能差)或太细(管理复杂) - 注意ABA问题(CAS需配合版本号使用) - 使用工具检测竞态条件(如ThreadSanitizer)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值