ScheduledExecutorService

任務調度(三)——Timer的替代品ScheduledExecutorService簡介

標籤: 任務調度TimerScheduledExecutorSer
5704人閱讀 評論(2) 收藏 舉報
category_icon.jpg分類:

       先前的兩篇博文《任務調度(一)——jdk自帶的Timer》和《任務調度(二)——jdk自帶的Timer 動態修改任務執行計劃》中,簡單介紹了一下Timer,可以實現幾本的功能,但是在多線程方面卻略顯不足。


       根據Timer源碼,可以看到Timer是單線程的。所以task都是串行執行。假如其中一個task執行需要很長的時間,那其他的task只能乾巴巴的等着。怎麼辦!


      現在就遇到了這樣的問題。總不能因爲這個小小的問題就去換別的任務調度框架吧,還是想用最簡單的方案去解決一下。所以ScheduledExecutorService就被我選中了。這個是怎麼找到的?1.網上搜,2.好好的看Timer類的註釋:


       翻譯一下:java5.0引入了Java.util.concurrent包,其中java.util.concurrent.scheduledthreadpoolexecutor就是在併發實用工具其中之一。scheduledthreadpoolexecutor是一個可以重複執行任務的線程池,並且可以指定任務的間隔和延遲時間。它作爲比Timer/TimerTask更加通用的替代品。因爲它允許多個服務線程,接受不同的時間單位,且不需要繼承TimeTask(僅僅需要實現Runnable接口)。配置ScheduledThreadPoolExecutor爲單線程,則與使用Timer等效。


       ScheduledThreadPoolExecutor實現了ScheduledExecutorService接口,所以標題中使用了接口的名字。

       ScheduledExecutorService提供了4個方法:


       其中第二個方法比較特殊一點,第一個參數是Callable,別的都是Runnable,二者的區別不再這篇博文的討論範圍之內。就此略過。說一些其他三個方法。

       schedule()方法第一個參數是任務實例,第二個參數是延遲時間,第三個是時間單元。比如調用如下:

  1. ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);  
  2. pool.schedule(task1, 5, TimeUnit.SECONDS);//延遲5s後,執行且只執行一次task1  
	ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
	pool.schedule(task1, 5, TimeUnit.SECONDS);//延遲5s後,執行且只執行一次task1

       scheduleAtFixedRate()和scheduleWithFixedDelay方法參數是一樣的。第一個參數是任務實例,第二個參數是延遲時間,第三個是間隔時間,第四個是時間單元。這兩個方法的不同之處在方法名也能看得出來:scheduleAtFixedRate方法是按照固定頻率去執行任務的。而scheduleWithFixedDelay方法則是按照固定的延遲去執行任務。

  1. /**  
  2.  * task1 
  3.  *  
  4.  * @author arron 
  5.  * @date 2015年8月5日 下午2:08:34  
  6.  * @version 1.0  
  7.  */  
  8. public class Task1 implements Runnable{  
  9.   
  10.     @SuppressWarnings("deprecation")  
  11.     public void run() {  
  12.         System.out.println("----task1 start--------"+new Date().toLocaleString());  
  13.         try {  
  14.             Thread.sleep(3000);  
  15.         } catch (InterruptedException e) {  
  16.             // TODO Auto-generated catch block  
  17.             e.printStackTrace();  
  18.         }  
  19.         System.out.println("----3s later, task1 end--------"+new Date().toLocaleString());  
  20.     }  
  21.       
  22. }  
/** 
 * task1
 * 
 * @author arron
 * @date 2015年8月5日 下午2:08:34 
 * @version 1.0 
 */
public class Task1 implements Runnable{

	@SuppressWarnings("deprecation")
	public void run() {
		System.out.println("----task1 start--------"+new Date().toLocaleString());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("----3s later, task1 end--------"+new Date().toLocaleString());
	}
	
}
測試scheduleAtFixedRate方法:
  1. public static void main(String[] args) {  
  2.       
  3.     ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);  
  4.       
  5.     Task1 t1 = new Task1();  
  6.     //立即執行t1,3s後任務結束,再等待2s(間隔時間-消耗時間),如果有空餘線程時,再次執行該任務  
  7.     pool.scheduleAtFixedRate(t1, 05, TimeUnit.SECONDS);  
  8.       
  9. }     
	public static void main(String[] args) {
		
		ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
		
		Task1 t1 = new Task1();
		//立即執行t1,3s後任務結束,再等待2s(間隔時間-消耗時間),如果有空餘線程時,再次執行該任務
		pool.scheduleAtFixedRate(t1, 0, 5, TimeUnit.SECONDS);
		
	}	
       執行結果如圖:

       task1第二次執行的前提是,當前有空餘的線程。

       執行的開始時間則是上一次結束時間+(間隔時間-任務消耗的時間)。加入這個差值小於0,即間隔時間小於任務消耗的時間,那就不會再等待,會立即執行(當然得滿足前提)。


測試scheduleAtFixedRate方法:

  1. public static void main(String[] args) {  
  2.       
  3.     ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);  
  4.       
  5.     Task1 t1 = new Task1();  
  6.     //立即執行t1,3s後任務結束,再等待5s(間隔時間-消耗時間),如果有空餘線程時,再次執行該任務  
  7.     pool.scheduleWithFixedDelay(t1, 05, TimeUnit.SECONDS);  
  8.       
  9. }     
	public static void main(String[] args) {
		
		ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
		
		Task1 t1 = new Task1();
		//立即執行t1,3s後任務結束,再等待5s(間隔時間-消耗時間),如果有空餘線程時,再次執行該任務
		pool.scheduleWithFixedDelay(t1, 0, 5, TimeUnit.SECONDS);
		
	}	
       執行結果如圖:


       就簡單介紹到這裏,下篇將會分享替換Timer的代碼。


1
0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章