spring quartz使用多線程併發「陷阱」(轉)

定義一個job:ranJob,設置每秒執行一次,設置不容許覆蓋併發執行java

    <bean id="rankJob" class="com.chinacache.www.logstat.job.RankJob" />  
    <bean id="rankJobDetail"  
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
        <property name="targetObject" ref="rankJob" />  
        <property name="targetMethod" value="execute" />  
        <property name="concurrent" value="false" />  
    </bean>  
    <bean id="rankJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
        <property name="jobDetail" ref="rankJobDetail" />  
        <!-- 單位 ms,半小時 1800000 ms -->  
        <property name="repeatInterval" value="1000 />  
    </bean>  

java 代碼spring

public void execute() throws InterruptedException {  
        System.out.println("Start job");  
        ExecutorService exec = Executors.newFixedThreadPool(1);  
          
        Thread thread = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                System.out.println("thread start");  
                try {  
                    Thread.sleep(3000);  
                } catch (InterruptedException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
                System.out.println("thread end");  
            }  
        });  
        exec.execute(thread);  
        exec.shutdown();  
           while (!exec.isTerminated()) {  
               // 等待全部子線程結束,才退出主線程  
           }          
        System.out.println("end job");  
    }  

 

打印結果以下:多線程

    Start job  
    thread start  
    thread end  
    end job  
      
    Start job  
    thread start  
    thread end  
    end job  
      
    Start job  
    thread start  
    thread end  
    end job  

使用isTerminated()方法等多線程結束後在結束job;多線程任務派發結束後,要使用shutdown()方法順序關閉線程(等待正在執行任務,不接受新任務)併發

 

定義一個job:ranJob,設置每秒執行一次,設置不容許覆蓋併發執行ide

  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代碼:spa

  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");  

 

程序輸出結果:線程

  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沒有關注多線程執行狀況code

修改job代碼,添加以下代碼在job訪問最後,線程處理完job才結束,xml

 

  1. while (!exec.isTerminated()) {  
  2.     // 等待全部子線程結束,才退出主線程  
  3. }  

 

修改代碼後程序結果:blog

  1. Start job  
  2. thread start  
  3. thread end  

 

能夠看到job始終沒有結束,說明ExecutorService始終沒有終止,看看文檔,加入shutdonw()方法,job全部代碼以下:

  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. }  

 

打印結果以下:

 

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

相關文章
相關標籤/搜索