1. 程式人生 > >ScheduledExecutorService中scheduleAtFixedRate與scheduleWithFixedDelay的區別

ScheduledExecutorService中scheduleAtFixedRate與scheduleWithFixedDelay的區別

 昨天重構藍芽指令傳送模組,按照設想,當連續傳送指令時,每條指令至少間隔30ms,於是構造了一個指令佇列,傳送時把指令放入佇列中,然後每隔30ms去佇列中取出指令執行,如果佇列為空,則掛起當前執行緒,很自然的想到BlockingQueue+ScheduledExecutorService,實現很簡單,但在專案中並沒有按照預期執行,於是寫一個demo分析下,直接上程式碼。


public class CommandSchedule {

    private ScheduledExecutorService mCommandService;
    private LinkedBlockingQueue<String> mCommandQueue
; public CommandSchedule() { mCommandService = Executors.newScheduledThreadPool(1); mCommandQueue = new LinkedBlockingQueue<>(); mCommandService.scheduleAtFixedRate(new Runnable() { long lastTime = System.currentTimeMillis(); @Override
public void run() { try { String commandBean = mCommandQueue.take(); if (commandBean != null) { System.out.println("time = " + (System.currentTimeMillis() - lastTime)); lastTime = System.currentTimeMillis
(); } } catch (InterruptedException e) { e.printStackTrace(); } } }, 0, 30, TimeUnit.MILLISECONDS); } public void postQueue(String str) { mCommandQueue.offer(str); } }


測試程式碼


public static void main(String[] args) {
    CommandSchedule schedule = new CommandSchedule();
    for(int i=0;i<10;i++){
        schedule.postQueue("");
    }
}


執行結果




沒什麼問題,每30ms執行了一次,接下來我1000ms後再呼叫postQueue


public static void main(String[] args) {
    CommandSchedule schedule = new CommandSchedule();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    for(int i=0;i<10;i++){
        schedule.postQueue("");
    }
}


執行結果



這顯然不符合我的期望,將方法替換成scheduleWithFixedDelay,結果和第一次執行一樣

很容易從結果看到它們之間的區別,就不多說了,有興趣的自行看jdk原始碼。