任務調度(四)——ScheduledExecutorService替代Timer,實現多線程任務調度


       上篇博文《任務調度(三)——Timer的替代品ScheduledExecutorService簡介》已經對ScheduledExecutorService做了簡介。事實上使用ScheduledExecutorService來替代Timer也是迫不得已的事情。

主要原因例如以下:

  1. Timer不支持多線程。全部掛在Timer下的任務都是單線程的,任務僅僅能串行運行。假設當中一個任務運行時間過長。會影響到其它任務的運行,然后就可能會有各種接踵而來的問題。

  2. Timer的線程不捕獲異常。TimerTask假設拋出異常,那么Timer唯一的進程就會掛掉,這樣掛在Timer下的全部任務都會無法繼續運行。

       第一個問題,隨着業務數據的猛增,我們生產上有幾個任務如今每次運行須要1-3個小時。在這段時間內,該timer下的其它任務僅僅能等待,這是讓人無法忍受的。重開一個Timer?難道要為全部的耗時的Task都單開一個Timer。顯然是不太可能。這樣就太亂了。


       第二個問題。是極其致命的。

好多業務數據都是晚上的定時任務跑出來的。結果因為程序的問題或者內存資源不足,導致線程被kill了。該timer下的全部任務都未運行。結果第二天整整忙活了一天,主要任務就是——跑任務,調整數據。

深受其害呀!



       為了彌補Timer的缺陷,jdk1.5中引入了並發包。這里面提供的ScheduledExecutorService。詳細實現類是:ScheduledThreadPoolExecutor。ScheduledThreadPoolExecutor支持多線程。同一時候在線程中對異常進行了捕獲。

所以是Timer的完美替換者。


       分享一個實例吧:

/** 
 * task2
 * @author arron
 * @date 2015年8月5日 下午2:08:34 
 * @version 1.0 
 */
public class Task2 extends TimerTask{

	@SuppressWarnings("deprecation")
	@Override
	public void run() {
		System.out.println("----task2 start--------"+new Date().toLocaleString());
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("----5s later, task2 end--------"+new Date().toLocaleString());
	}
}
       測試代碼:
	public static void main(String[] args) {

		ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);//啟用2個線程
		
		Task1 t1 = new Task1();
		// 馬上運行,任務消耗3秒。運行結束后等待2秒。【有空余線程時】,再次運行該任務
		pool.scheduleWithFixedDelay(t1, 0, 2, TimeUnit.SECONDS);
		
		// 馬上運行,任務消耗5秒,運行結束后等待2秒。【有空余線程時】,再次運行該任務
		Task2 t2 = new Task2();
		pool.scheduleWithFixedDelay(t2, 0, 2, TimeUnit.SECONDS);
		
	}
       運行結果如圖:



       這樣任務之間就不會相互影響了。並且能夠同一時候運行。可是線程數量要設置好了。

過渡添加線程數也會適得其反。


免責聲明!

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



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