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

關(guān)于線程池異步線程中再次獲取線程池資源的問題

 更新時間:2024年08月20日 10:33:56   作者:BlueKitty1210  
這篇文章主要介紹了關(guān)于線程池異步線程中再次獲取線程池資源的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

問題描述

在線上發(fā)生的一次問題,在場景中有這樣一個業(yè)務,需要異步執(zhí)行一個主任務,主任務中又包含著N個子任務,為了整個主任務能夠快速處理,又將子任務按照數(shù)量獲取線程資源異步處理,即異步線程A中再異步調(diào)用A1,A2,A3. A可能同時存在多個.

實際場景中,由于系統(tǒng)線程池分配數(shù)量較小,且一段時間內(nèi)先后啟動了多個主任務,耗時的主任務中又用子任務取申請線程導致線程池資源耗盡

問題原因

1. 主任務是從線程池中獲取的線程資源,同時主任務比較耗時?

2. 每個主任務中包含的N的子任務,會再申請線程,處理完畢釋放回線程池

3. 啟動了多個主任務時,每個主任務在未結(jié)束之前,都會占用自身一個線程不會釋放,消耗一個線程池資源

4. 后期頻繁啟動主任務,可能使數(shù)量=線程池線程數(shù),此時子任務無法再從線程池獲得資源,就進入隊列等待

5. 最終結(jié)果就造成了每個主任務都占用線程,但主任務內(nèi)的子任務無法獲取線程,線程池癱瘓不可用

問題復現(xiàn)

package test;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @title 線程池異步線程中再次獲取線程池資源的問題
 * @author Xingbz
 * @description
 *  記;
 *
 *  究其原因在于:
 *      
 * @createDate 2020-7-17
 */
@Slf4j
public class TestWork {

    private static final ThreadPoolTaskExecutor EXECUTOR;

    static {
        EXECUTOR = myExecutor();
    }

    /** 初始化線程池 */
    public static ThreadPoolTaskExecutor myExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心線程數(shù)
        executor.setCorePoolSize(5);
        // 最大線程數(shù)
        executor.setMaxPoolSize(20);
        // 排隊任務隊列
        executor.setQueueCapacity(100);
        // 線程名稱前綴
        executor.setThreadNamePrefix("異步線程-");
        // 隊列滿后拒絕策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 線程最大回收時間
        executor.setKeepAliveSeconds(100);
        // 初始化線程
        executor.initialize();
        return executor;
    }

    /** 模擬測試 */
    public static void main(String[] args) throws Exception {
        // 主任務數(shù)量
        int mainJobNum = 20;

        CountDownLatch mainDownLatch = new CountDownLatch(mainJobNum);

        for (int i = 0; i < mainJobNum; i++) {
            // 主任務編號, 方便區(qū)分
            int index = i + 1;

            // 模擬每1秒開始一個主任務
            TimeUnit.SECONDS.sleep(1);

            EXECUTOR.submit(() -> {
                try {
                    log.debug("\t執(zhí)行主任務" + index);

                    // 每個主任務隨機包含N個子任務, 再異步調(diào)用線程池資源處理
                    int subJobNum = RandomUtils.nextInt(2, 3);
                    subJobWorkAsync(subJobNum, index);
                } finally {
                    mainDownLatch.countDown();
                }
            });
        }

        mainDownLatch.await();
        EXECUTOR.shutdown();
        log.info("完成所有任務 > > >");
    }

    /** 異步執(zhí)行子任務 */
    private static void subJobWorkAsync(int subJobNum, int index) {
        CountDownLatch subDownLatch = new CountDownLatch(subJobNum);
        for (int j = 0; j < subJobNum; j++) {
            EXECUTOR.submit(() -> {
                try {
                    log.warn("\t\t\t執(zhí)行一個" + index + "的子任務");
                    // 每個子任務模擬耗時
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    subDownLatch.countDown();
                }
            });
        }

        try {
            subDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

執(zhí)行代碼,結(jié)果如下:

可以看到,線程池很快就被主任務耗盡, 導致子任務無法執(zhí)行.

解決方案

1. 異步線程中不能再獲取異步線程

既然主方法是異步執(zhí)行了,那么其中的子任務也相對不那么要求時間.此處是我為了業(yè)務給另外一個業(yè)務復用導致了線程再調(diào)線程

2. 如果異步中確實需要再獲取異步線程,需要使用新的線程池. 不能再使用自身的線程池

這是當前我們的解決方案,在系統(tǒng)中又單獨構(gòu)建了一個線程池負責子任務的業(yè)務

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

潮安县| 佳木斯市| 新昌县| 巴林左旗| 从江县| 雷州市| 秭归县| 江北区| 五常市| 钟祥市| 缙云县| 营口市| 九龙城区| 安丘市| 吉林省| 榆林市| 阳东县| 甘洛县| 丰宁| 泗洪县| 双峰县| 开平市| 徐闻县| 个旧市| 威海市| 高邮市| 陈巴尔虎旗| 清远市| 莱阳市| 淄博市| 万州区| 济源市| 越西县| 平邑县| 东台市| 鄂尔多斯市| 德清县| 徐汇区| 庄河市| 湖南省| 黄陵县|