Java之——Timer與ScheduledExecutorService__Java

來源:互聯網
上載者:User

轉載請註明出處:http://blog.csdn.net/l1028386804/article/details/48050505

java.util.Timer計時器有管理工作順延強制("如1000ms後執行任務")以及周期性執行("如每500ms執行一次該任務")。 但是,Timer存在一些缺陷,因此你應該考慮使用ScheduledThreadPoolExecutor作為代替品,Timer對調度的支援是基於絕對時間,而不是相對時間的,
由此任務對系統時鐘的改變是敏感的;ScheduledThreadExecutor只支援相對時間。

Timer的另一個問題在於,如果TimerTask拋出未檢查的異常,Timer將會產生無法預料的行為。
Timer線程並不捕獲異常,所以TimerTask拋出的未檢查的異常會終止timer線程。
這種情況下,Timer也不會再重新恢複線程的執行了;它錯誤的認為整個Timer都被取消了。
此時,已經被安排但尚未執行的TimerTask永遠不會再執行了,新的任務也不能被調度了。
 

個人總結:timer的bug:60秒執行一次的話,如果使用者修改了時間的話 那麼時針都會歸0,本來是臨近10秒執行的時候timer又會重新計時一次 再等60才執行。

測試Timer例子:

package com.lyz.test;    import java.util.Timer;  import java.util.TimerTask;  /** * 測試Timer樣本程式 * @author liuyazhuang */  public class TimerTest {      private Timer timer = new Timer();      //啟動計時器      public void lanuchTimer(){          timer.schedule(new TimerTask(){              public void run() {                  throw new RuntimeException();              }          }, 1000*3, 500);      }      //向計時器添加一個任務      public void addOneTask(){          timer.schedule(new TimerTask(){              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();      }  }
運行該程式,Timer會拋出一個RumtimeException和java.lang.IllegalStateException:Timer already cancelled.
常言道,真是禍不單行,Timer還將它的問題傳染給下一個倒黴的調用者,這個調用者原本試圖提交一個TimerTask的,你可能希望程式會一直運行下去,然而實際情況如程式所示5秒鐘後就中止了,還伴隨著一個異常,異常的訊息是"Timer already cancelled"。ScheduledThreadPoolExector妥善地處理了這個異常的任務,所以說在java5.0或更高的JDK中,幾乎沒有理由再使用Timer了。

Timer的測試結果所圖所示

用ScheduledThreadPoolExector改進後的例子

package com.lyz.test;    import java.util.concurrent.Executors;  import java.util.concurrent.ScheduledExecutorService;  import java.util.concurrent.TimeUnit;    /** * ScheduledThreadPoolExector測試程式 * @author liuyazhuang * */public class ScheduledExecutorTest {      //線程池能按時間計劃來執行任務,允許使用者設定計劃執行任務的時間,int類型的參數是設定      //線程池中線程的最小數目。當任務較多時,線程池可能會自動建立更多的背景工作執行緒來執行任務      //此處用Executors.newSingleThreadScheduledExecutor()更佳。    public ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(1);      //啟動計時器      public void lanuchTimer(){          Runnable task = new Runnable() {              public void run() {                  throw new RuntimeException();              }          };          scheduExec.scheduleWithFixedDelay(task, 1000*5, 1000*10, TimeUnit.MILLISECONDS);      }      //添加新任務      public void addOneTask(){          Runnable task = new Runnable() {              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 {          ScheduledExecutorTest test = new ScheduledExecutorTest();          test.lanuchTimer();          Thread.sleep(1000*5);//5秒鐘之後添加新任務          test.addOneTask();      }  }
從下面的運行截圖可以看出,即使計時器內部發生了異常也不影響正常的調用,你不必擔心ScheduleExecutor會發生異常而導致計時器停止,而Timer則會因為異常而停止。





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.