Java 定時任務

定時任務就是在指定時間執行程序,或週期性執行計劃任務。Java中實現定時任務的方法有不少,本文從從JDK自帶的一些方法來實現定時任務的需求。

Timer和TimerTask

  • schedule和scheduleAtFixedRate函數都是阻塞式的,若是定時任務的執行時間大於定時任務的定時週期,則下個週期的定時任務會在前個週期的任務完成後纔會啓動。
  • 定時任務是單線程的,同一時間只能執行一個定時任務
  • 執行定時任務時,如出現一個未捕獲異常致使任務退出,那下個週期的定時任務也不會啓動,因此定時任務必定要用try catch。
public class JavaTimeTest {

    private final static Logger logger = Logger.getLogger("JavaTimeTest");
    public JavaTimeTest() {
    }

    public static void main(String[] args) {
        class Test1 extends TimerTask {
            @Override
            public void run() {
                logger.info("begin running=========");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                logger.info("end running=========");
            }
        }
        new Timer().scheduleAtFixedRate(new Test1(), 0, 1000);
    }
}
測試結果:
十一月 15, 2016 9:40:11 下午 com.zzl.JavaTimeTest run
信息: begin running=========
十一月 15, 2016 9:40:14 下午 com.zzl.JavaTimeTest run
信息: end running=========
十一月 15, 2016 9:40:14 下午 com.zzl.JavaTimeTest run
信息: begin running=========
十一月 15, 2016 9:40:17 下午 com.zzl.JavaTimeTest run
信息: end running=========
十一月 15, 2016 9:40:17 下午 com.zzl.JavaTimeTest run
信息: begin running=========
十一月 15, 2016 9:40:20 下午 com.zzl.JavaTimeTest run
信息: end running=========
十一月 15, 2016 9:40:20 下午 com.zzl.JavaTimeTest run
信息: begin running=========

###ScheduledExecutorServiceide

  • Timer對調度的支持是基於絕對時間,而不是相對時間的,由此任務對系統時鐘的改變是敏感的;ScheduledThreadExecutor只支持相對時間。
  • 若是TimerTask拋出未檢查的異常,Timer將會產生沒法預料的行爲。Timer線程並不捕獲異常,因此 TimerTask拋出的未檢查的異常會終止timer線程。此時,已經被安排但還沒有執行的TimerTask永遠不會再執行了,新的任務也不能被調度了。 ####缺點:依然是阻塞式的方式,若是定時任務的執行時間大於執行週期,下一次定時任務須要在前一次定時任務執行完畢以後才能執行。
public class ScheduleTimerTest {
    private final static Log log = LogFactory.getLog(ScheduleTimerTest.class);

    public ScheduleTimerTest() {
    }

    public static void main(String[] args) {
        class Test1 extends TimerTask {
            @Override
            public void run() {
                log.info("begin running=========");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("end running=========");
            }
        }
        //注意:直接將Test1做爲scheduleWithFixedDelay的參數,定時任務仍是會要在上次任務運行完以後才執行下次任務
        //所以,如今定時任務只是每分鐘建立一個任務,真正的任務執行是在新建的線程中再執行
        ScheduledExecutorService executor = Executors
                .newScheduledThreadPool(10);
        executor.scheduleWithFixedDelay(
                new Test1(),
                0,  //delay
                1, //頻率
                TimeUnit.SECONDS);
    }
}
測試結果:
十一月 15, 2016 9:50:28 下午 com.zzl.ScheduleTimerTest run
信息: begin running=========
十一月 15, 2016 9:50:31 下午 com.zzl.ScheduleTimerTest run
信息: end running=========
十一月 15, 2016 9:50:32 下午 com.zzl.ScheduleTimerTest run
信息: begin running=========
十一月 15, 2016 9:50:35 下午 com.zzl.ScheduleTimerTest run
信息: end running=========
十一月 15, 2016 9:50:36 下午 com.zzl.ScheduleTimerTest run
信息: begin running=========
十一月 15, 2016 9:50:39 下午 com.zzl.ScheduleTimerTest run
信息: end running=========
十一月 15, 2016 9:50:40 下午 com.zzl.ScheduleTimerTest run
信息: begin running=========
相關文章
相關標籤/搜索