spring quartz使用多線程並發“陷阱”(轉)


定義一個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()方法順序關閉線程(等待正在執行任務,不接受新任務)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM