版權聲明:本文爲博主原創文章,未經博主允許不得轉載。如需轉載請聲明:【轉自 http://blog.csdn.net/xiaoxian8023 】
先前的兩篇博文《任務調度(一)——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
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());
- }
- }
/**
* 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);
- }
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);
- }
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的代碼。
- 頂
- 1
- 踩
- 0