成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java多線程(4):使用線程池執(zhí)行定時任務

Nekron / 3580人閱讀

摘要:的類圖如下實現(xiàn)了接口,繼承了接口,所以首先是一個線程池,然后除了具有線程池的功能,它還有定時和周期性執(zhí)行任務的功能。

在現(xiàn)實世界里,我們總是免不了要定期去做一件事情(比如上課)—— 在計算機的世界里,更是如此。比如我們手機每天叫我們起床的電子鬧鐘,某些網(wǎng)站會定期向我們發(fā)送一些推薦相關(guān)的郵件,集群中我們需要每隔一定時間檢查是否有機器宕機等。

使用線程池 中已經(jīng)介紹,JDK 1.5 時,標準類庫添加了對線程池的支持,然后在線程池核心實現(xiàn) ThreadPoolExecutor 的基礎(chǔ)上,實現(xiàn)了 ScheduledThreadPoolExecutor,作為可以 定時和周期性執(zhí)行任務 的線程池。ScheduledThreadPoolExecutor 的類圖如下:

ScheduledThreadPoolExecutor 實現(xiàn)了 ScheduledExecutorService 接口,ScheduledExecutorService 繼承了 ExecutorService 接口,所以首先 ScheduledThreadPoolExecutor 是一個 ExecutorService (線程池),然后除了具有線程池的功能,它還有定時和周期性執(zhí)行任務的功能。ScheduledExecutorService 除了從 ExecutorService 繼承的方法外,還包括如下四個方法:

第一個 Schedule 方法:

delay 指定的時間后,執(zhí)行指定的 Runnable 任務,可以通過返回的 ScheduledFuture 與該任務進行交互。

第二個 Schedule 方法:

delay 指定的時間后,執(zhí)行指定的 Callable 任務,可以通過返回的 ScheduledFuture 與該任務進行交互。

ScheduledFuture 接口 繼承自 Future 接口,所以 ScheduledFuture 和任務的交互方式與 Future 一致。所以通過ScheduledFuture,可以 判斷定時任務是否已經(jīng)完成,獲得定時任務的返回值,或者取消任務等)

scheduleAtFixedRate 方法:

initialDelay 指定的時間后,開始按周期 period 執(zhí)行指定的 Runnable 任務。
假設(shè)調(diào)用該方法后的時間點為 0,那么第一次執(zhí)行任務的時間點為 initialDelay,第二次為 initialDelay + period,第三次為 initialDelay + period + period,以此類推。

scheduleWithFixedDelay 方法:

initialDelay 指定的時間后,開始按指定的 delay 延期性的執(zhí)行指定的 Runnable 任務。
假設(shè)調(diào)用該方法后的時間點為 0,每次任務需要耗時 T(i)i 為第幾次執(zhí)行任務),那么第一次執(zhí)行任務的時間點為 initialDelay,第一次完成任務的時間點為 initialDelay + T(1),則第二次執(zhí)行任務的時間點為 initialDelay + T(1) + delay;第二次完成任務的時間點為 initialDelay + (T(1) + delay) + T(2),所以第三次執(zhí)行任務的時間點為 initialDelay + T(1) + delay + T(2) + delay,以此類推。

我們來實踐下 ScheduledThreadPoolExecutorscheduleAtFixedRate 方法:

public class ScheduledExecutorServiceTest {

    public static void main(String[] args) throws Exception {
        ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
        
        TimerTask timerTask = new TimerTask(2000); // 任務需要 2000 ms 才能執(zhí)行完畢

        System.out.printf("起始時間:%s

", new SimpleDateFormat("HH:mm:ss").format(new Date()));

        // 延時 1 秒后,按 3 秒的周期執(zhí)行任務
        timer.scheduleAtFixedRate(timerTask, 1000, 3000, TimeUnit.MILLISECONDS);
    }

    private static class TimerTask implements Runnable {

        private final int sleepTime;
        private final SimpleDateFormat dateFormat;

        public TimerTask(int sleepTime) {
            this.sleepTime = sleepTime;
            dateFormat = new SimpleDateFormat("HH:mm:ss");
        }

        @Override
        public void run() {
            System.out.println("任務開始,當前時間:" + dateFormat.format(new Date()));

            try {
                System.out.println("模擬任務運行...");
                Thread.sleep(sleepTime);
            } catch (InterruptedException ex) {
                ex.printStackTrace(System.err);
            }

            System.out.println("任務結(jié)束,當前時間:" + dateFormat.format(new Date()));
            System.out.println();
        }

    }
}

運行結(jié)果:

可以看到運行結(jié)果完全符合預期 —— 延時 1 秒后,每隔 3 秒執(zhí)行一次任務。

上面是任務的運行時間小于周期時間的情況 —— 那如果任務運行的時間大于給定的執(zhí)行周期呢?(比如任務運行需要 3 s,但是我們指定的周期為 2 s)

修改 main 方法:

public static void main(String[] args) throws Exception {
    ScheduledExecutorService timer = Executors.newScheduledThreadPool(2);

    TimerTask timerTask = new TimerTask(3000); // 每個任務需要 3000 ms 才能執(zhí)行完畢

    System.out.printf("起始時間:%s

", new SimpleDateFormat("HH:mm:ss").format(new Date()));

    timer.scheduleAtFixedRate(timerTask, 1000, 2000, TimeUnit.MILLISECONDS);
}

運行結(jié)果:

可以看到此時雖然我們指定的周期為 2 s,但是因為任務的運行就需要 3 s(超過周期),所以這種情況下 scheduleAtFixedRate 的處理方式為 上一次任務剛完成,則緊接著立即運行下一次任務,而不是使用線程池中的空閑線程來運行任務以維護 2 秒這個周期 —— 由此可見,每個定時任務在 ScheduledThreadPoolExecutor 中,都是串行運行的,即下一次運行任務一定在上一次任務結(jié)束之后。

scheduleWithFixedDelay 方法 的使用也十分簡單,請有興趣的讀者自己實踐)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66448.html

相關(guān)文章

  • Java并發(fā)編程之線程線程

    摘要:目標線程由運行狀態(tài)轉(zhuǎn)換為就緒狀態(tài),也就是讓出執(zhí)行權(quán)限,讓其他線程得以優(yōu)先執(zhí)行,但其他線程能否優(yōu)先執(zhí)行時未知的。函數(shù)的官方解釋是意思是使調(diào)用該函數(shù)的線程讓出執(zhí)行時間給其他已就緒狀態(tài)的線程。 線程允許在同一個進程中同時存在多個程序控制流,即通過線程可以實現(xiàn)同時處理多個任務的功能。線程會共享進程范圍內(nèi)的資源,例如內(nèi)存句柄和文件句柄,但每個線程都有各自的程序計數(shù)器、棧以及局部變量。 多線程的實...

    wums 評論0 收藏0
  • SpringBoot中并發(fā)定時任務的實現(xiàn)、動態(tài)定時任務的實現(xiàn)(看這一篇就夠了)

    摘要:也是自帶的一個基于線程池設(shè)計的定時任務類。其每個調(diào)度任務都會分配到線程池中的一個線程執(zhí)行,所以其任務是并發(fā)執(zhí)行的,互不影響。 原創(chuàng)不易,如需轉(zhuǎn)載,請注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責任?。。?一、在JAVA開發(fā)領(lǐng)域,目前可以通過以下幾種方式進行定時任務 1、單機部署模式 Timer:jdk中...

    BWrong 評論0 收藏0
  • Java 線程并發(fā)編程面試筆錄一覽

    摘要:創(chuàng)建線程的方式方式一將類聲明為的子類。將該線程標記為守護線程或用戶線程。其中方法隱含的線程為父線程。恢復線程,已過時。等待該線程銷毀終止。更多的使當前線程在鎖存器倒計數(shù)至零之前一直等待,除非線 知識體系圖: showImg(https://segmentfault.com/img/bVbef6v?w=1280&h=960); 1、線程是什么? 線程是進程中獨立運行的子任務。 2、創(chuàng)建線...

    bitkylin 評論0 收藏0
  • java高并發(fā)系列 - 第19天:JUC中的Executor框架詳解1,全面掌握java并發(fā)相關(guān)技術(shù)

    摘要:有三種狀態(tài)運行關(guān)閉終止。類類,提供了一系列工廠方法用于創(chuàng)建線程池,返回的線程池都實現(xiàn)了接口。線程池的大小一旦達到最大值就會保持不變,在提交新任務,任務將會進入等待隊列中等待。此線程池支持定時以及周期性執(zhí)行任務的需求。 這是java高并發(fā)系列第19篇文章。 本文主要內(nèi)容 介紹Executor框架相關(guān)內(nèi)容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...

    icattlecoder 評論0 收藏0

發(fā)表評論

0條評論

Nekron

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<