線程池延時(shí)類ScheduledExecutorService—比Timer更有效精確的延時(shí)工具

ScheduledExecutorService

前言

??在Java中我們一般使用Timer來進(jìn)行延時(shí)/周期執(zhí)行操作,Timer的內(nèi)部只有一個線程,如果有多個任務(wù)的話就會順序執(zhí)行,這樣我們的延遲時(shí)間和循環(huán)時(shí)間就會出現(xiàn)問題。除此之外:在多線程并發(fā)執(zhí)行定時(shí)操作時(shí),Timer運(yùn)行多個TimerTask,如果其中一個任務(wù)沒有異常沒有捕獲,那所有任務(wù)都將終止。還有就是,Timer是基于絕對時(shí)間,而ScheduledExecutorService是基于相對時(shí)間的,這個看情況而定,一般基于相對時(shí)間更靈活一些。所以作為Timer的替代品,在對延遲任務(wù)和循環(huán)任務(wù)要求嚴(yán)格的時(shí)候,最好使用ScheduledExecutorService。
ScheduledExecutorService提供了三種方法來進(jìn)行延時(shí)/周期操作:schedule、scheduleAtFixedRate、scheduleWithFixedDelay。

schedule方法

ScheduledExecutorService用于延遲一段時(shí)間后執(zhí)行任務(wù)或者周期性的執(zhí)行任務(wù).通常使用Executor類的工廠方法去實(shí)例化一個ScheduledExecutorService是一個比較好的方式。.

 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1000);
//延遲兩秒打印fsd,這里使用了lamda表達(dá)式簡化,相當(dāng)于new Runable()
 scheduledThreadPool.schedule(() ->System.out.println("fsd"), 2, TimeUnit.SECONDS);

scheduleAtFixedRate方法

scheduleAtFixedRate()方法在延遲一段時(shí)間之后周期性的執(zhí)行一個任務(wù).下面的代碼將會先延遲1秒之后首次執(zhí)行,之后每隔3秒執(zhí)行,不管任務(wù)耗時(shí)多久,3秒后都立即執(zhí)行下一個任務(wù)。

    ScheduledExecutorService  executorService =Executors.newSingleThreadScheduledExecutor();
//第一次延遲一秒打印,后每三秒打印一次,這里使用了lamda表達(dá)式簡化,相當(dāng)于new Runable()
    executorService.scheduleAtFixedRate(() ->System.out.println("fsd"),1,3,TimeUnit.SECONDS);

總結(jié)一下就是:scheduleAtFixedRate是按照上一次任務(wù)的發(fā)起時(shí)間計(jì)算下一次任務(wù)的開始時(shí)間。

scheduleWithFixedDelay方法

如果需要任務(wù)周期性執(zhí)行的時(shí)候保持固定的時(shí)間間隔,應(yīng)該使用scheduleWithFixedDalay()方法.如下的代碼保證上一次任務(wù)執(zhí)行完(不管多久)過10秒之后再執(zhí)行下一次任務(wù).

    ScheduledExecutorService  executorService =Executors.newSingleThreadScheduledExecutor();
//第一次延遲一秒打印,后每三秒打印一次,這里使用了lamda表達(dá)式簡化,相當(dāng)于new Runable()
    executorService.scheduleWithFixedDelay(() ->System.out.println("fsd"),1,3,TimeUnit.SECONDS);

總結(jié)一下就是:.scheduleWithFixedDelay以上一次任務(wù)的結(jié)束時(shí)間計(jì)算下一次任務(wù)的開始時(shí)間
**注意:
如果ExecutorService被關(guān)閉,或者在任務(wù)執(zhí)行過程中拋出了一個異常,那么周期性執(zhí)行的任務(wù)將會終止.。所以最好在Runable中的run方法中捕獲所有異常,保證循環(huán)的進(jìn)行,如下:

public class MyThread implements Runnable{
 @Override
    public void run() {
        try { 
            int sleepNumber = random.nextInt(3);
            if(sleepNumber ==2){
                    int error = 1/0;
                        }
        } catch (Exception e) {
            e.printStackTrace();
        }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容