使用 ScheduledExecutorService 來替換 Timer

java.util.Timer計時器有管理任務延遲執行("如1000ms後執行任務")以及週期性執行("如每500ms執行一次該任務")。java

可是,Timer存在一些缺陷:ide

1,Timer對調度的支持是基於絕對時間,而不是相對時間的,由此任務對系統時鐘的改變是敏感的;ScheduledThreadExecutor只支持相對時間。 oop

2,若是TimerTask拋出未檢查的異常,Timer將會產生沒法預料的行爲。Timer線程並不捕獲異常,因此 TimerTask拋出的未檢查的異常會終止timer線程。此時,已經被安排但還沒有執行的TimerTask永遠不會再執行了,新的任務也不能被調度了。 測試

 測試代碼:spa

public class ScheduledExecutorTest {
	public static void main(String[] args) throws Exception {
		final ScheduledExecutorTest test = new ScheduledExecutorTest();
		// test.lanuchTimer();
		// Thread.sleep(1000*5);//5秒鐘以後添加新任務
		// test.addOneTask();
		test.lanuchTimer2();
		Thread.sleep(1000 * 5);// 5秒鐘以後添加一個新任務
		test.addOneTask2();
	}

	private final Timer timer = new Timer();

	// 啓動計時器
	public void lanuchTimer2() {
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				throw new RuntimeException();
			}
		}, 1000 * 3, 500);
	}

	// 向計時器添加一個任務
	public void addOneTask2() {
		timer.schedule(new TimerTask() {
			@Override
			public void run() {
				System.out.println("hello world");
			}
		}, 1000 * 1, 1000 * 5);
	}

	// public static void main(String[] args) throws Exception {
	// TimerTest test = new TimerTest();
	// test.lanuchTimer();
	// Thread.sleep(1000*5);//5秒鐘以後添加一個新任務
	// test.addOneTask();
	// }
}

測試代碼結果:
線程

Exception in thread "Timer-0" java.lang.RuntimeException
	at com.technology.test.ScheduledExecutorTest$3.run(ScheduledExecutorTest.java:78)
	at java.util.TimerThread.mainLoop(Unknown Source)
	at java.util.TimerThread.run(Unknown Source)
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.
	at java.util.Timer.sched(Unknown Source)
	at java.util.Timer.schedule(Unknown Source)
	at com.technology.test.ScheduledExecutorTest.addOneTask2(ScheduledExecutorTest.java:85)
	at com.technology.test.ScheduledExecutorTest.main(ScheduledExecutorTest.java:68)

那麼若是使用ScheduledExecutorService呢?日誌

測試代碼以下:code

public class ScheduledExecutorTest {
	// 線程池能按時間計劃來執行任務,容許用戶設定計劃執行任務的時間,int類型的參數是設定
	// 線程池中線程的最小數目。當任務較多時,線程池可能會自動建立更多的工做線程來執行任務
	public ScheduledExecutorService scheduExec = Executors
			.newScheduledThreadPool(1);

	// 啓動計時器
	public void lanuchTimer() {
		final Runnable task = new Runnable() {
			@Override
			public void run() {
				throw new RuntimeException();
			}
		};
		scheduExec.scheduleWithFixedDelay(task, 1000 * 5, 1000 * 10,
				TimeUnit.MILLISECONDS);
	}

	// 添加新任務
	public void addOneTask() {
		final Runnable task = new Runnable() {
			@Override
			public void run() {
				System.out.println("welcome to china");
			}
		};
		scheduExec.scheduleWithFixedDelay(task, 1000 * 1, 1000,
				TimeUnit.MILLISECONDS);
	}

	public static void main(String[] args) throws Exception {
		final ScheduledExecutorTest test = new ScheduledExecutorTest();
		// test.lanuchTimer();
		// Thread.sleep(1000*5);//5秒鐘以後添加新任務
		// test.addOneTask();

		test.lanuchTimer();
		Thread.sleep(1000 * 5);// 5秒鐘以後添加一個新任務
		test.addOneTask();
	}

}
輸入日誌信息爲:

welcome to china
welcome to china
welcome to china

程序能正確的輸出。it

相關文章
相關標籤/搜索