22
京東網上商城
ScheduledExecutorService和timer的異同
先來個傳統的Timer的例子:
[java]
view plaincopy
- package com.jerry.concurrency;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Timer;
- import java.util.TimerTask;
- public class TraditionalTask {
- public static void main(String[] args) throws ParseException {
- Timer myTimer = new Timer();
- myTimer.schedule(new Worker(), 1000);//1秒後執行
- // 2012-02-28 09:58:00執行
- myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"));
- myTimer.schedule(new Worker(), 5000,1000);//5秒後執行 每一秒執行一次
- // 2012-02-28 09:58:00執行一次 以後每秒執行一次,如果設定的時間點在當前時間之前,任務會被馬上執行,然後開始按照設定的周期定時執行任務
- myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);
- myTimer.scheduleAtFixedRate(new Worker(), 5000,1000);//5秒後執行 每一秒執行一次 如果該任務因為某些原因(例如垃圾收集)而延遲執行,那麼接下來的任務會盡可能的快速執行,以趕上特定的時間點
- myTimer.scheduleAtFixedRate(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);//和上個類似
- }
- }
- class Worker extends TimerTask {
- @Override
- public void run() {
- System.out.println("我被執行了!"+"時間是:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
- }
- }
傳統的timer的缺點:Timer對任務的調度是基於絕對時間的;所有的TimerTask隻有一個線程TimerThread來執行,因此同一時刻隻有一個TimerTask在執行;任何一個TimerTask的執行異常都會導致Timer終止所有任務;由於基於絕對時間並且是單線程執行,因此在多個任務調度時,長時間執行的任務被執行後有可能導致短時間任務快速在短時間內被執行多次或者幹脆丟棄多個任務。
ScheduledExecutorService克服了上述缺點,例子如下:
[java]
view plaincopy
- <span style="font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;font-size:13px;">package com.jerry.concurrency;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- public class TestScheduledExecutorService{
- public static void main(String[] args) throws Exception{
- ScheduledExecutorService execService = Executors.newScheduledThreadPool(3);
- // 5秒後開始執行 每個2秒執行一次,如果有的任務執行要花費比其周期更長的時間,則將推遲後續執行,但不會同時執行
- // 每次相隔相同的時間執行任務,如果任務的執行時間比周期還長,那麼下一個任務將立即執行
- execService.scheduleAtFixedRate(new Runnable() {
- public void run() {
- System.out.println("任務:"+Thread.currentThread().getName()+" 執行了,時間為: "+System.currentTimeMillis());
- try {
- Thread.sleep(1000L);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }, 5, 2, TimeUnit.SECONDS);
- //5秒後開始執行 每個2秒執行一次,保證固定的延遲為2秒 下一個任務的開始時間與上一個任務的結束時間間隔相同
- execService.scheduleWithFixedDelay(new Runnable() {
- public void run() {
- System.out.println("任務:"+Thread.currentThread().getName()+"執行了,時間為:"+System.currentTimeMillis());
- try {
- Thread.sleep(1000L);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }, 5, 2, TimeUnit.SECONDS);
- Thread.sleep(10000L);
- execService.shutdown();
- }
- }
- </span>
最後更新:2017-04-03 20:19:30