一、推薦使用的調度器和線程池
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....");
}
}