初識 ScheduledThreadPoolExecutor

將如下代碼保存到Wzf.java文件,使用javac編譯,使用java運行即可。

Wzf.java

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import java.util.Date;
import java.text.SimpleDateFormat;

public class Wzf {
    private ScheduledExecutorService mGeneratorExecutor;
    private ScheduledFuture<?> mDataItemGeneratorFuture;

    public static void main(String[] args) {
       Wzf wzf = new Wzf();
       wzf.init();
       wzf.start();
    }

    public void init() {
        log("init", "init begin");
        mGeneratorExecutor = new ScheduledThreadPoolExecutor(1);
        log("init", "init end");
    }

    public void start() {
        log("start", "start begin");
        mDataItemGeneratorFuture = mGeneratorExecutor.scheduleWithFixedDelay(//scheduleAtFixedRate
                new DataItemGenerator(), 1, 5, TimeUnit.SECONDS);
        log("start", "start end");
    }

    public void stop() {
        log("stop", "stop begin");
        mDataItemGeneratorFuture.cancel(true /* mayInterruptIfRunning */);
        log("stop", "stop end");
    }

    private class DataItemGenerator implements Runnable {
        @Override
        public void run() {
            log("run", "run.......111");
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
            }
            log("run", "run.......222");
        }
    }

    private void log(String tag, String msg) {
        long tId = Thread.currentThread().getId();
        String tName = Thread.currentThread().getName();
        
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss..SSS");
        String timeStr = df.format(new Date());
        System.out.println(timeStr + "    " + tName + "[" + tId + "]  " + tag + " : " + msg);
    }
}

運行log如下

2016-02-20 15:39:31..867    main[1]  init : init begin
2016-02-20 15:39:31..869    main[1]  init : init end
2016-02-20 15:39:31..870    main[1]  start : start begin
2016-02-20 15:39:31..871    main[1]  start : start end
2016-02-20 15:39:32..883    pool-1-thread-1[8]  run : run.......111
2016-02-20 15:39:35..892    pool-1-thread-1[8]  run : run.......222
2016-02-20 15:39:40..906    pool-1-thread-1[8]  run : run.......111
2016-02-20 15:39:43..916    pool-1-thread-1[8]  run : run.......222
2016-02-20 15:39:48..922    pool-1-thread-1[8]  run : run.......111
2016-02-20 15:39:51..933    pool-1-thread-1[8]  run : run.......222
2016-02-20 15:39:56..938    pool-1-thread-1[8]  run : run.......111
從log看,執行start之後,循環在其他線程中處理某項事務,第一次延遲1s執行,其餘都是延遲5s執行。兩個時間間隔是用參數設置的。


scheduleWithFixedDelay與scheduleAtFixedRate的區別:

前者是固定的時間間隔,即前一個事務處理完之後,間隔5s,再執行下一個事務處理。

後者是固定的頻率,即兩次事務開始處理的時間間隔是5s。如果事務處理比較耗時,超過了間隔時間,則會在前一個事務處理完後,馬上開始執行下一個事務處理。


Timer與ScheduledThreadPoolExecutor的區別:
Timer對調度的支持是基於絕對時間的,因此任務對系統時間的改變是敏感的;而ScheduledThreadPoolExecutor支持相對時間。
Timer使用單線程方式來執行所有的TimerTask,如果某個TimerTask很耗時則會影響到其他TimerTask的執行;
而ScheduledThreadPoolExecutor則可以構造一個固定大小的線程池來執行任務。
Timer 不會捕獲由TimerTask拋出的未檢查異常,故當有異常拋出時,Timer會終止,導致未執行完的TimerTask不再執行,新的 TimerTask也不能被調度;
ScheduledThreadPoolExecutor對這個問題進行了妥善的處理,不會影響其他任務的執行。


獲取系統當前時間,並格式化,顯示毫秒:

import java.util.Date;
import java.text.SimpleDateFormat;

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss..SSS");
String timeStr = df.format(new Date());

參考:

http://hubingforever.blog.163.com/blog/static/17104057920109643632988/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章