ScheduledThreadPoolExecutor使用指南


ScheduledThreadPoolExecutor是Timer的多線程實現版本,JDK官方推薦使用。
ScheduledThreadPoolExecutor用於替代Timer。是接口ScheduledExecutorService的子類,主要方法說明如下:

/** 
 * 調度一個task,經過delay(時間單位由參數unit決定)后開始進行調度,僅僅調度一次 
 */  
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);  

/** 
 * 同上,支持參數不一樣 
 */  
public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);  

/** 
 * 周期性調度任務,在delay后開始調度,適合執行時間比“間隔”短的任務 
 * 並且任務開始時間的間隔為period,即“固定間隔”執行。 
 * 如果任務執行的時間比period長的話,會導致該任務延遲執行,不會同時執行! 
 * 如果任務執行過程拋出異常,后續不會再執行該任務! 
 */  
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay ,long period ,TimeUnit unit);  

/** 
 * Timer所沒有的“特色”方法,稱為“固定延遲(delay)”調度,適合執行時間比“間隔”長的任務 
 * 在initialDelay后開始調度該任務 
 * 隨后,在每一次執行終止和下一次執行開始之間都存在給定的延遲period 
 * 即下一次任務開始的時間為:上一次任務結束時間(而不是開始時間) + delay時間 
 * 如果任務執行過程拋出異常,后續不會再執行該任務! 
 */  
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay ,long delay ,TimeUnit unit);

 

示例代碼:

import java.util.concurrent.Executors;  
import java.util.concurrent.ScheduledExecutorService;  
import java.util.concurrent.TimeUnit;  

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();  
    }  
}

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才執行。

示例代碼:

import java.util.Timer;  
import java.util.TimerTask;  

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();  
    }  
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM