最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java線程池ExecutorService超時處理小結(jié)

 更新時間:2024年09月26日 10:23:04   作者:小百菜  
使用ExecutorService時,設(shè)置子線程執(zhí)行超時是一個常見需求,本文就來詳細(xì)的介紹一下ExecutorService超時的三種方法,感興趣的可以了解一下

場景問題:使用線程池ExecutorService,想設(shè)置每個子線程的執(zhí)行超時時間,使用future.get()來監(jiān)聽超時,當(dāng)有子線程阻塞時,導(dǎo)致有的隊列任務(wù)還未執(zhí)行就被取消了。

方式一、使用 future.get() 來監(jiān)聽超時取消

這種辦法看似能解決問題,但是當(dāng)任務(wù)累積處理不過來時,會漏執(zhí)行。
比如下面的例子,就實際只會執(zhí)行一個子線程。

package com.study;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;

public class Test {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final ExecutorService threadPool = Executors.newFixedThreadPool(1);

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            Future<?> future = threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(LocalDateTime.now().format(formatter));
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        // e.printStackTrace();
                    }
                }
            });
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        future.get(3, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (TimeoutException e) {//超時異常
                        future.cancel(true); // 超時后取消任務(wù)
                    }
                }
            }).start();
        }
    }
}

方式二、在子線程內(nèi)部,超時后去發(fā)送中斷信號

package com.study;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;

public class Test {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final ExecutorService threadPool = Executors.newFixedThreadPool(1);
    private static final ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(1);//監(jiān)聽超時,這個數(shù)量要和線程池數(shù)量相同

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            // int delay = 3;
            int delay = i + 1;
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    ScheduledFuture<?> schedule = null;
                    try {
                        Thread thread = Thread.currentThread();
                        // 啟動一個定時器,如果任務(wù)執(zhí)行超過3秒則中斷當(dāng)前線程
                        schedule = timeoutExecutor.schedule(() -> {
                            thread.interrupt(); // 中斷當(dāng)前正在執(zhí)行的任務(wù)
                        }, delay, TimeUnit.SECONDS);
                        System.out.println(LocalDateTime.now().format(formatter));
                        Thread.sleep(5000);
                        // FileOutputStream fos = new FileOutputStream("d:/test.txt" + k);
                        // for (int j = 0; j < 1000000; j++) {
                        //     fos.write("123".getBytes());
                        // }
                        // fos.close();
                    } catch (InterruptedException e) {
                        // e.printStackTrace();
                    } finally {
                        if (schedule != null) {
                            //取消任務(wù)
                            schedule.cancel(true);
                        }
                    }
                }
            });
        }
    }
}

這里其實還是有問題 ,把 Thread.sleep(5000);改成注釋的io阻塞,還是要等線程執(zhí)行結(jié)束后才會取消線程執(zhí)行。

所以單純使用  future 是實現(xiàn)不了這個場景的邏輯的。

timeoutExecutor 數(shù)量和 線程池數(shù)量要一致的原因如下示例。

package com.study;

import java.time.LocalDateTime;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorServiceExample {

    private static final ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(2);

    public static void main(String[] args) throws InterruptedException {
        // 調(diào)用schedule方法兩次
        scheduleTask("Task 1");
        scheduleTask("Task 2");
        scheduleTask("Task 3");
    }

    private static void scheduleTask(String taskName) {
        timeoutExecutor.schedule(() -> {
            System.out.println(taskName + " started at: " + LocalDateTime.now());
            try {
                // 模擬任務(wù)執(zhí)行
                Thread.sleep(2000); // 假設(shè)每個任務(wù)執(zhí)行2秒
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, 3, TimeUnit.SECONDS);
    }
}

方式三、自己定義鎖來實現(xiàn)

package com.study;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;

public class Test {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final ExecutorService threadPool = Executors.newFixedThreadPool(16);//這里不能設(shè)置為1了,這里已經(jīng)不是用來控制并發(fā)數(shù)量了,只是為了重復(fù)利用線程
    private static final ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(1);//監(jiān)聽超時,這個數(shù)量要和線程池數(shù)量相同

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(50);
            // int delay = 3;
            int delay = i + 1;
            int k = i;
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    ScheduledFuture<?> schedule = null;
                    try {
                        ThreadPool.awaitThread();
                        // 啟動一個定時器,如果任務(wù)執(zhí)行超過3秒則中斷當(dāng)前線程
                        // timeoutExecutor如果只有一個線程池,這里面的代碼片段會阻塞,上一個線程在這里的代碼片段執(zhí)行完后,當(dāng)前線程才會執(zhí)行這里的代碼片段,
                        // 但是影響不大,因為這里的代碼片段只是釋放動作,一瞬間就會執(zhí)行完,所以影響不大,
                        // 如果其他場景這里阻塞時間比較久,那么timeoutExecutor線程大小要和threadPool線程大小一致。
                        schedule = timeoutExecutor.schedule(() -> {
                            System.out.println("釋放1");
                            ThreadPool.releaseThread();
                        }, delay, TimeUnit.SECONDS);
                        System.out.println("【" + Thread.currentThread().getName() + "】" + LocalDateTime.now().format(formatter));
                        Thread.sleep(5000);
                        // FileOutputStream fos = new FileOutputStream("d:/test.txt" + k);
                        // for (int j = 0; j < 1000000; j++) {
                        //     fos.write("123".getBytes());
                        // }
                        // fos.close();
                    } catch (Exception e) {
                        System.out.println("異常");
                    } finally {
                        if (schedule != null) {
                            //cancel返回true任務(wù)還未執(zhí)行,需要取消任務(wù)
                            if (schedule.cancel(true)) {
                                System.out.println("釋放2");
                                ThreadPool.releaseThread();
                            }
                        }
                    }
                }
            });
        }
    }
}
package com.study;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 線程池
 */
public class ThreadPool {
    private static final int MAX_POOL_SIZE = 1; // 最大線程數(shù),控制并發(fā)數(shù)量
    private static int totalThread = 0; // 總線程數(shù)
    private static final Lock lock = new ReentrantLock(true);
    private static final Condition notice = lock.newCondition();

    /**
     * 從線程池獲取線程
     */
    public static boolean awaitThread() {
        lock.lock();
        try {
            // 嘗試從線程池中獲取線程
            if (totalThread < MAX_POOL_SIZE) {
                totalThread++;
                return true;
            }
            // 線程已到達(dá)最大線程數(shù),等待歸還線程,最長等待1小時,await()會釋放當(dāng)前線程的鎖
            if (notice.await(1, TimeUnit.HOURS)) {
                totalThread++;
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return false;
    }


    /**
     * 釋放線程到線程池
     */
    public static void releaseThread() {
        lock.lock();
        try {
            totalThread--;
            // 通知有空閑,signal()會喚醒其中一個await()線程
            notice.signal();
        } finally {
            lock.unlock();
        }
    }

}

到此這篇關(guān)于java線程池ExecutorService超時處理小結(jié)的文章就介紹到這了,更多相關(guān)java線程池ExecutorService超時內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Intellij idea下使用不同tomcat編譯maven項目的服務(wù)器路徑方法詳解

    Intellij idea下使用不同tomcat編譯maven項目的服務(wù)器路徑方法詳解

    今天小編就為大家分享一篇關(guān)于Intellij idea下使用不同tomcat編譯maven項目的服務(wù)器路徑方法詳解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • JAVA中Collections.sort()方法使用詳解

    JAVA中Collections.sort()方法使用詳解

    這篇文章主要給大家介紹了關(guān)于JAVA中Collections.sort()方法使用的相關(guān)資料,Java中Collections.sort()方法是用來對List類型進(jìn)行排序的,文中通過代碼將使用的方法介紹的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • Java多線程編程之讀寫鎖ReadWriteLock用法實例

    Java多線程編程之讀寫鎖ReadWriteLock用法實例

    這篇文章主要介紹了Java多線程編程之讀寫鎖ReadWriteLock用法實例,本文直接給出編碼實例,需要的朋友可以參考下
    2015-05-05
  • @RequestBody注解的原理及使用技巧分享

    @RequestBody注解的原理及使用技巧分享

    這篇文章主要介紹了@RequestBody注解的原理及使用技巧分享,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 三張圖徹底了解Java中字符串的不變性

    三張圖徹底了解Java中字符串的不變性

    這篇文章主要通過三張圖徹底幫助大家了解Java中字符串的不變性,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Spring Data Redis中Hash結(jié)構(gòu)操作技巧與最佳實踐

    Spring Data Redis中Hash結(jié)構(gòu)操作技巧與最佳實踐

    本文全面掌握Spring Data Redis中Hash結(jié)構(gòu)的操作技巧與最佳實踐,包括節(jié)省內(nèi)存、支持單字段更新和查詢、原子性操作等,通過SpringDataRedis的opsForHash(),可以方便地進(jìn)行Hash結(jié)構(gòu)的操作,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • SpringBoot整合Kotlin構(gòu)建Web服務(wù)的方法示例

    SpringBoot整合Kotlin構(gòu)建Web服務(wù)的方法示例

    這篇文章主要介紹了SpringBoot整合Kotlin構(gòu)建Web服務(wù)的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • 淺談MyBatis 如何執(zhí)行一條 SQL語句

    淺談MyBatis 如何執(zhí)行一條 SQL語句

    Mybatis 是 Java 開發(fā)中比較常用的 ORM 框架。在日常工作中,我們都是直接通過 Spring Boot 自動配置,并直接使用,但是卻不知道 Mybatis 是如何執(zhí)行一條 SQL 語句的,下面就一起講解一下
    2021-05-05
  • 使用springboot activiti關(guān)閉驗證自動部署方式

    使用springboot activiti關(guān)閉驗證自動部署方式

    這篇文章主要介紹了使用springboot activiti關(guān)閉驗證自動部署方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • mybatis?like模糊查詢特殊字符報錯轉(zhuǎn)義處理方式

    mybatis?like模糊查詢特殊字符報錯轉(zhuǎn)義處理方式

    這篇文章主要介紹了mybatis?like模糊查詢特殊字符報錯轉(zhuǎn)義處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評論

都昌县| 嘉义县| 古丈县| 石景山区| 崇礼县| 柳州市| 德安县| 邯郸县| 武乡县| 景德镇市| 扎囊县| 鸡西市| 台山市| 安图县| 芜湖县| 乐业县| 鹿泉市| 肇州县| 江阴市| 颍上县| 垫江县| 年辖:市辖区| 鹤庆县| 陇川县| 邯郸市| 中卫市| 海宁市| 肇源县| 泰宁县| 金山区| 司法| 临澧县| 凤山县| 马山县| 无极县| 洛阳市| 新巴尔虎左旗| 林甸县| 夹江县| 读书| 江永县|