欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文帶你學(xué)會Java中ScheduledThreadPoolExecutor使用

 更新時間:2024年12月15日 11:06:48   作者:JWASX  
ScheduledThreadPoolExecutor是Java并發(fā)包中的一個類,同時也是?ThreadPoolExecutor的一個子類,本文主要為大家介紹一下ScheduledThreadPoolExecutor使用,需要的可以參考下

1. 概要

前面文章的地址:

定時/延時任務(wù)-自己實現(xiàn)一個簡單的定時器

定時/延時任務(wù)-Timer用法

ScheduledThreadPoolExecutor 是 Java 并發(fā)包 (java.util.concurrent) 中的一個類,同時也是 ThreadPoolExecutor 的一個子類,這就意味者 ScheduledThreadPoolExecutor 不像 Timer 中使用單個線程去執(zhí)行任務(wù),ScheduledThreadPoolExecutor 使用了線程池去執(zhí)行,同時 ScheduledThreadPoolExecutor 也具備了 Timer 中的各種功能。

2. 固定速率和固定延時

2.1 固定速率

固定速率 策略表示任務(wù)在固定的時間間隔內(nèi)重復(fù)執(zhí)行,不管任務(wù)的執(zhí)行時間有多長,如果任務(wù)的執(zhí)行時間超過了時間間隔,那么下一個任務(wù)會在當(dāng)前任務(wù)執(zhí)行完畢之后就會馬上開始執(zhí)行,下面是一個例子:假設(shè)我們設(shè)置了一個固定速率為 5 的任務(wù),從 0s 開始執(zhí)行,也就是說這個任務(wù) 5s 執(zhí)行一次:

  • 第一次執(zhí)行: 在 0s 開始執(zhí)行一次,假設(shè)執(zhí)行時間是 3s
  • 第二次執(zhí)行: 在 5s 開始執(zhí)行第二次,假設(shè)執(zhí)行的時候被阻塞了,執(zhí)行了 8s
  • 第三次執(zhí)行: 在 13s 開始執(zhí)行第三次,假設(shè)執(zhí)行的時候被阻塞了,執(zhí)行了 3s
  • 第四次執(zhí)行: 在 16s 開始執(zhí)行第四次,假設(shè)執(zhí)行的時候沒有被阻塞
  • 第四次執(zhí)行: 在 20s 開始執(zhí)行第五次,假設(shè)執(zhí)行的時候沒有被阻塞

2.2 固定延時

固定延時 策略表示任務(wù)在當(dāng)前任務(wù)執(zhí)行完成之后,固定延時一段時間再執(zhí)行下一個任務(wù),下面是一個例子:假設(shè)我們設(shè)置了一個固定速率為 5 的任務(wù),從 0s 開始執(zhí)行,也就是說這個任務(wù) 5s 執(zhí)行一次:

  • 第一次執(zhí)行: 在 0s 開始執(zhí)行一次,假設(shè)執(zhí)行時間是 3s
  • 第二次執(zhí)行: 在 8s 開始執(zhí)行第二次,假設(shè)執(zhí)行的時候被阻塞了,執(zhí)行了 8s
  • 第三次執(zhí)行: 在 21s 開始執(zhí)行第三次,假設(shè)執(zhí)行的時候被阻塞了,執(zhí)行了 3s
  • 第四次執(zhí)行: 在 29 開始執(zhí)行第四次,假設(shè)執(zhí)行的時候沒有被阻塞
  • 第四次執(zhí)行: 在 34s 開始執(zhí)行第五次,假設(shè)執(zhí)行的時候沒有被阻塞

上面的例子中其實固定速率的執(zhí)行和 Timer 是一樣的,但是固定延時有點(diǎn)不一樣,不知道你有沒有發(fā)現(xiàn),固定延時下執(zhí)行的時候每一個任務(wù)和前一個任務(wù)的時間間隔一定是 任務(wù)執(zhí)行時間 + 延時時間,其實相比于 Timer,ScheduledThreadPoolExecutor 的固定延時看起來更像是 “正宗” 一點(diǎn)的固定延時

3. API 解釋

3.1 schedule

還是老規(guī)矩,先看下 ScheduledThreadPoolExecutor 的幾個 API,看看用法是什么樣的,首先就是 schedule 方法,這個方法就是普通的延時方法,只執(zhí)行一次,非周期調(diào)度

public class Pra {

    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(16);
        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                if (Math.random() < 0.5) {
                    System.out.println("sleep: 3s");
                    Thread.sleep(3000);
                } else {
                    System.out.println("sleep: 8s");
                    Thread.sleep(8000);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "thread-executor-run");
        executor.schedule(thread, 0, TimeUnit.SECONDS);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

執(zhí)行結(jié)果如下所示,延遲 0s 就開始執(zhí)行任務(wù)

ScheduledThreadPoolExecutor 也提供了一個 callable 類型的任務(wù)的實現(xiàn),使用 Callable 的好處就是可以獲取任務(wù)的實現(xiàn)返回值,如下例子所示:

public class Pra {

    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(16);

        // 創(chuàng)建一個 Callable 任務(wù)
        Callable<Integer> task = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println("Task is running on thread: " + Thread.currentThread().getName());
                return 1; // 返回結(jié)果
            }
        };

        // 調(diào)度 Callable 任務(wù),在 0 秒后執(zhí)行
        ScheduledFuture<Integer> future = executor.schedule(task, 0, TimeUnit.SECONDS);
        try {
            // 獲取任務(wù)的結(jié)果
            Integer result = future.get();
            System.out.println("Task result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

輸出結(jié)果如下所示:

3.2 固定延時 - scheduleWithFixedDelay

public class Pra {

    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(16);

        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                if (Math.random() < 0.5) {
                    System.out.println("sleep: 3s");
                    Thread.sleep(3000);
                } else {
                    System.out.println("sleep: 8s");
                    Thread.sleep(8000);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "thread-executor-run");

        executor.scheduleWithFixedDelay(thread, 0, 5, TimeUnit.SECONDS);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

輸入如下所示:

來分析一下:

首先第一次任務(wù) 2024-11-24 19:19:36:698 啟動,然后執(zhí)行時間 3s

第二次任務(wù)在 2024-11-24 19:19:44:718 啟動,跟第一次任務(wù)相差 8s,延時 = 5s + 3s = 8s

第三次任務(wù)在 2024-11-24 19:19:52:741 啟動,跟第二次任務(wù)相差 8s,延時 = 5s + 3s = 8s

第四次任務(wù)在 2024-11-24 19:20:05:760 啟動,跟第三次任務(wù)相差 13s,延時 = 5s + 8s = 13s

第五次任務(wù)在 2024-11-24 19:20:13:773 啟動,跟第四次任務(wù)相差 8s,延時 = 5s + 3s = 8s

第六次任務(wù)在 2024-11-24 19:20:26:787 啟動,跟第五次任務(wù)相差 13s,延時 = 5s + 8s = 13s

可以看到 scheduleWithFixedDelay 的延時是相對于當(dāng)前時間 + 延時時間的,跟 Timer 的固定延時任務(wù)有點(diǎn)不同

3.2 固定速率 - scheduleWithFixedDelay

public class Pra {

    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(16);

        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread-Current: " + Thread.currentThread().getName() + ", time = " + getTime());
                if (Math.random() < 0.5) {
                    System.out.println("sleep: 3s");
                    Thread.sleep(3000);
                } else {
                    System.out.println("sleep: 8s");
                    Thread.sleep(8000);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "thread-executor-run");

        executor.scheduleAtFixedRate(thread, 0, 5, TimeUnit.SECONDS);
    }

    private static String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        return sdf.format(new Date());
    }

}

輸出結(jié)果如下:

來分析下上面的執(zhí)行流程,需要注意的是,ScheduledThreadPoolExecutor 的固定速率任務(wù)會在當(dāng)前任務(wù)執(zhí)行完之后再添加下一次要執(zhí)行的任務(wù)

  • 首先第一次任務(wù) 2024-11-24 16:23:25:762 啟動,然后執(zhí)行時間 8s,執(zhí)行完之后會添加一個 2024-11-24 16:23:30 s 執(zhí)行的任務(wù),當(dāng)前時間 2024-11-24 16:23:33 s
  • 第二次任務(wù)在 2024-11-24 16:23:33:770 啟動,因為 2024-11-24 16:23:33:770 超過了 2024-11-24 16:23:30 s 這個時間點(diǎn), 所以立刻執(zhí)行,執(zhí)行時間 3s,執(zhí)行完之后往隊列里面添加一個 2024-11-24 16:23:35 s 執(zhí)行的任務(wù),當(dāng)前時間 2024-11-24 16:23:36 s
  • 第二次任務(wù)在 2024-11-24 16:23:36:784 啟動,因為 2024-11-24 16:23:36:784 超過了 2024-11-24 16:23:35 s 這個時間點(diǎn), 所以立刻執(zhí)行,執(zhí)行時間 3s,執(zhí)行完之后往隊列里面添加一個 2024-11-24 16:23:40 s 執(zhí)行的任務(wù),當(dāng)前時間 2024-11-24 16:23:39 s
  • 第四次任務(wù)在 2024-11-24 16:23:40:739 啟動,因為第三個任務(wù)執(zhí)行完之后時間是 2024-11-24 16:23:39 s,還沒有到第四個任務(wù)執(zhí)行的時間點(diǎn),這時候就等待,等到 2024-11-24 16:23:40:739,執(zhí)行時間 3s,執(zhí)行完之后往隊列里面添加一個 2024-11-24 16:23:45 s 執(zhí)行的任務(wù),執(zhí)行完的時間當(dāng)前是 2024-11-24 16:23:42 s
  • 第五次任務(wù)在 2024-11-24 16:23:45:751 啟動,因為第四個任務(wù)執(zhí)行完之后時間是 2024-11-24 16:23:42 s,還沒有到第五個任務(wù)執(zhí)行的時間點(diǎn),這時候就等待,等到 2024-11-24 16:23:45:751,執(zhí)行時間 8s,執(zhí)行完之后往隊列里面添加一個 2024-11-24 16:23:50 s 執(zhí)行的任務(wù),執(zhí)行完的時間當(dāng)前是 2024-11-24 16:23:53 s
  • 第六次任務(wù)在 2024-11-24 16:23:53:763 啟動,因為第六個任務(wù)執(zhí)行時間是 2024-11-24 16:23:50 s,而執(zhí)行完第五個任務(wù)已經(jīng)是 2024-11-24 16:23:53 s了,超過任務(wù)的執(zhí)行時間,所以會立馬執(zhí)行,執(zhí)行時間 3s,執(zhí)行完后往隊列里面添加一個 2024-11-24 16:23:55 s 的任務(wù),當(dāng)前時間是 2024-11-24 16:23:56 s

其實上面的解釋中可以把后面的毫秒去掉,這樣比較方便理解

4. 小結(jié)

上面就是幾個 API 了,其中固定速率的和 Timer 的實現(xiàn)方式有點(diǎn)不同,后續(xù)文章中,我會對 ScheduledThreadPoolExecutor 的源碼進(jìn)行詳細(xì)的解析,當(dāng)然在解析 ScheduledThreadPoolExecutor 之前首先需要知道下線程池的工作原理和工作流程。

以上就是一文帶你學(xué)會Java中ScheduledThreadPoolExecutor使用的詳細(xì)內(nèi)容,更多關(guān)于Java ScheduledThreadPoolExecutor的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java如何利用策略模式替代if/else語句

    Java如何利用策略模式替代if/else語句

    這篇文章主要介紹了Java如何利用策略模式替代if/else語句,幫助大家優(yōu)化自己的代碼,提高程序運(yùn)行效率,感興趣的朋友可以了解下
    2020-09-09
  • Java多線程之CAS機(jī)制詳解

    Java多線程之CAS機(jī)制詳解

    這篇文章主要介紹了Java多線程之CAS機(jī)制詳解,CAS指的是Compare-And-Swap(比較與交換),它是一種多線程同步的技術(shù),常用于實現(xiàn)無鎖算法,從而提高多線程程序的性能和擴(kuò)展性,需要的朋友可以參考下
    2023-07-07
  • Spring MVC過濾器-登錄過濾的代碼實現(xiàn)

    Spring MVC過濾器-登錄過濾的代碼實現(xiàn)

    本篇文章主要介紹了Spring MVC過濾器-登錄過濾,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧。
    2017-01-01
  • Java Arrays.sort()用法詳解

    Java Arrays.sort()用法詳解

    這篇文章主要介紹了Java Arrays.sort()用法詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Spring boot中filter類不能注入@Autowired變量問題

    Spring boot中filter類不能注入@Autowired變量問題

    這篇文章主要介紹了Spring boot中filter類不能注入@Autowired變量問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java開發(fā)中POJO和JSON互轉(zhuǎn)時如何忽略隱藏字段的問題

    Java開發(fā)中POJO和JSON互轉(zhuǎn)時如何忽略隱藏字段的問題

    這篇文章主要介紹了Java開發(fā)中POJO和JSON互轉(zhuǎn)時如何忽略隱藏字段的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • java用LocalDateTime類獲取當(dāng)天時間、前一天時間及本周/本月的開始和結(jié)束時間

    java用LocalDateTime類獲取當(dāng)天時間、前一天時間及本周/本月的開始和結(jié)束時間

    這篇文章主要給大家介紹了關(guān)于java使用LocalDateTime類獲取當(dāng)天時間、前一天時間及本周/本月的開始和結(jié)束時間的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • Java:

    Java:"失效"的private修飾符

    本文主要介紹Java 失效的private修飾符,這里整理了相關(guān)資料說明private 修飾符的作用,如何使用并與C++ 做比較,有興趣的小伙伴可以參考下
    2016-08-08
  • 詳解Java中的反射機(jī)制和動態(tài)代理

    詳解Java中的反射機(jī)制和動態(tài)代理

    本文將詳細(xì)介紹反射機(jī)制以及動態(tài)代理機(jī)制,而且基本現(xiàn)在的主流框架都應(yīng)用了反射機(jī)制,如spring、MyBatis、Hibernate等等,這就有非常重要的學(xué)習(xí)意義
    2021-06-06
  • SpringBoot多配置切換的配置方法

    SpringBoot多配置切換的配置方法

    這篇文章主要介紹了SpringBoot多配置切換的配置方法及spring boot設(shè)置端口和上下文路徑的方法,需要的朋友可以參考下
    2018-04-04

最新評論