一、推薦使用的調度器和線程池
1、調度器
//2個線程的調度器 private static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(2); //5秒鐘後每3分鐘執行一次 pool.scheduleAtFixedRate(new TestTask(), 5, 60 * 3, TimeUnit.SECONDS);
;
2、線程池
//10個線程的線程池 ExecutorService pool = Executors.newFixedThreadPool(10); //執行一個線程 pool.execute(new TestTask());
線程:
class TestTesk implements Runnable{ @Override public void run() { System.out.println("執行2...."); } }
二、timer和timertask
Timer是一種線程設施,用於安排以後在後台線程中執行的任務。可安排任務執行一次,或者定期重復執行,可以看成一個定時器,可以調度TimerTask。TimerTask是一個抽象類,實現了Runnable接口,所以具備了多線程的能力。
一個Timer可以調度任意多個TimerTask,它會將TimerTask存儲在一個隊列中,順序調度,如果想兩個TimerTask並發執行,則需要創建兩個Timer。下面來看一個簡單的例子:
import java.util.Timer; import java.util.TimerTask; public class TimerTest { static class MyTimerTask1 extends TimerTask { public void run() { System.out.println("爆炸!!!"); } } public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new MyTimerTask1(), 2000);// 兩秒後啟動任務 //已當前時間為起點,每隔兩秒執行一次 //timer.schedule(new MyTimerTask1(), new Date(), 2000);// 兩秒後啟動任務 } }
三、比較
Timer對調度的支持是基於絕對時間的,因此任務對系統時間的改變是敏感的;而ScheduledThreadPoolExecutor支持相對時間。
Timer使用單線程方式來執行所有的TimerTask,如果某個TimerTask很耗時則會影響到其他TimerTask的執行;而ScheduledThreadPoolExecutor則可以構造一個固定大小的線程池來執行任務。
Timer 不會捕獲由TimerTask拋出的未檢查異常,故當有異常拋出時,Timer會終止,導致未執行完的TimerTask不再執行,新的 TimerTask也不能被調度;ScheduledThreadPoolExecutor對這個問題進行了妥善的處理,不會影響其他任務的執行。
總結:timer任務一旦有一個出錯那麼所有的任務都會中斷,而ScheduledThreadPoolExecutor只會停止出錯任務而不會停止其他任務
下面是一個ScheduledThreadPoolExecutor出錯的例子:
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ScheduleTest { public static void main(String[] args) { ScheduledThreadPoolExecutor schedule = new ScheduledThreadPoolExecutor(2); schedule.scheduleAtFixedRate(new TestTesk(), 2, 5, TimeUnit.SECONDS); schedule.scheduleAtFixedRate(new TestTesk2(), 2, 5, TimeUnit.SECONDS); } } class TestTesk implements Runnable{ @Override public void run() { System.out.println("執行1...."); String a = null; System.out.println(a.length()); } } class TestTesk2 implements Runnable{ @Override public void run() { System.out.println("執行2...."); } }