spring quartz使用多线程并发“陷阱”(转)

本文解决SpringQuartz在多线程环境下出现的并发问题,通过合理使用ExecutorService的shutdown及isTerminated方法确保任务按预期执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义一个job:ranJob,设置每秒执行一次,设置不允许覆盖并发执行

 

Xml代码   收藏代码
  1. <bean id="rankJob" class="com.chinacache.www.logstat.job.RankJob" />  
  2. <bean id="rankJobDetail"  
  3.     class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
  4.     <property name="targetObject" ref="rankJob" />  
  5.     <property name="targetMethod" value="execute" />  
  6.     <property name="concurrent" value="<span style="color: #ff0000;"><strong>false</strong></span>/>  
  7. </bean>  
  8. <bean id="rankJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
  9.     <property name="jobDetail" ref="rankJobDetail" />  
  10.     <!-- 单位 ms,半小时 1800000 ms -->  
  11.     <property name="repeatInterval" value="<span style="color: #ff0000;"><strong>1000</strong></span>/>  
  12. </bean>  

 

job代码:

Java代码   收藏代码
  1. System.out.println("Start job");  
  2. ExecutorService exec = Executors.newFixedThreadPool(1);  
  3.   
  4. Thread thread = new Thread(new Runnable() {  
  5.     @Override  
  6.     public void run() {  
  7.         System.out.println("thread start");  
  8.         try {  
  9.             Thread.sleep(3000);  
  10.         } catch (InterruptedException e) {  
  11.             // TODO Auto-generated catch block  
  12.             e.printStackTrace();  
  13.         }  
  14.         System.out.println("thread end");  
  15.     }  
  16. });  
  17. exec.execute(thread);  
  18. System.out.println("end job");  

 

程序输出结果:

Java代码   收藏代码
  1. Start job  
  2. end job  
  3. <span style="color: #ff0000;"><strong>thread start</strong></span>  
  4. Start job  
  5. end job  
  6. thread start  
  7. Start job  
  8. end job  
  9. thread start  
  10. Start job  
  11. end job  
  12. thread start  
  13. <strong><span style="color: #ff0000;">thread end</span></strong>  

 

从结果可以看到,job的并发覆盖配置似乎根本没有生效,原因是:job没有关注多线程执行情况

修改job代码,添加如下代码在job访问最后,线程处理完job才结束,

 

Java代码   收藏代码
  1. while (!exec.isTerminated()) {  
  2.     // 等待所有子线程结束,才退出主线程  
  3. }  

 

修改代码后程序结果:

Java代码   收藏代码
  1. Start job  
  2. thread start  
  3. thread end  

 

可以看到job始终没有结束,说明ExecutorService始终没有终止,看看文档,加入shutdonw()方法,job所有代码如下:

Java代码   收藏代码
  1. public void execute() throws InterruptedException {  
  2.     System.out.println("Start job");  
  3.     ExecutorService exec = Executors.newFixedThreadPool(1);  
  4.       
  5.     Thread thread = new Thread(new Runnable() {  
  6.         @Override  
  7.         public void run() {  
  8.             System.out.println("thread start");  
  9.             try {  
  10.                 Thread.sleep(3000);  
  11.             } catch (InterruptedException e) {  
  12.                 // TODO Auto-generated catch block  
  13.                 e.printStackTrace();  
  14.             }  
  15.             System.out.println("thread end");  
  16.         }  
  17.     });  
  18.     exec.execute(thread);  
  19.     exec.shutdown();  
  20.        while (!exec.isTerminated()) {  
  21.            // 等待所有子线程结束,才退出主线程  
  22.        }          
  23.     System.out.println("end job");  
  24. }  

 

打印结果如下:

 

Java代码   收藏代码
  1. Start job  
  2. thread start  
  3. thread end  
  4. end job  
  5.   
  6. Start job  
  7. thread start  
  8. thread end  
  9. end job  
  10.   
  11. Start job  
  12. thread start  
  13. thread end  
  14. end job  

 

 

OK,至此spring quartz多线程并发问题解决。回顾下,我们要使用isTerminated()方法等多线程结束后在结束job;多线程任务派发结束后,要使用shutdown()方法顺序关闭线程(等待正在执行任务,不接受新任务)

转载于:https://www.cnblogs.com/dazhaxie/archive/2012/11/21/2780742.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值