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


       先前的兩篇博文《任務調度(一)——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()方法第一個參數是任務實例,第二個參數是延遲時間,第三個是時間單元。

比方調用例如以下:

	ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
	pool.schedule(task1, 5, TimeUnit.SECONDS);//延遲5s后,運行且僅僅運行一次task1

       scheduleAtFixedRate()和scheduleWithFixedDelay方法參數是一樣的。

第一個參數是任務實例,第二個參數是延遲時間。第三個是間隔時間,第四個是時間單元。

這兩個方法的不同之處在方法名也能看得出來:scheduleAtFixedRate方法是依照固定頻率去運行任務的。而scheduleWithFixedDelay方法則是依照固定的延遲去運行任務。

/** 
 * 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方法:
	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方法:

	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的代碼。



免責聲明!

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



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