線程池的使用

首先看看阿里java規(guī)范中對線程池使用的規(guī)范

image.png

不允許使用Executors創(chuàng)建線程池,創(chuàng)建的線程池數(shù)量可以為Integer.MAX_VALUE,可能導(dǎo)致OOM
推薦使用
ThreadPoolExecutor創(chuàng)建
看看其4構(gòu)造方法


image.png

看參數(shù)最多的一個,上面的都是調(diào)這個方法

       /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

翻譯一下
ThreadPoolExecutor(核心線程大小, 最大線程數(shù),線程保持時間,保持時間單位, 緩存隊列,線程工廠,拒絕策略)
前四個比較容易理解,看后面幾個就好了
緩存隊列:任務(wù)多的時候,沒有多余線程執(zhí)行任務(wù),這些任務(wù)去隊列排隊,先進先出的原則,這里隊列大小是有限制的,隊排滿了怎么辦,用后面的拒絕策略來處理
線程工廠:
繼承java.util.concurrent.ThreadFactory,下面是可用的兩個工廠

Executors.defaultThreadFactory();
Executors.privilegedThreadFactory();

拒絕策略:隊列滿了,后面的任務(wù)排不進去怎么處理,四種策略


image.png

1.AbortPolicy(終止策略)
這是一個處理器針對被拒絕的任務(wù) 直接拋出RejectedExecutionException異常(任務(wù)無法執(zhí)行拋出異常)

2.DiscardPolicy(丟棄策略)
什么都不做,也不拋出異常

3.DiscardOldestPolicy(丟棄舊任務(wù)策略)
一種被拒絕任務(wù)的處理程序,它丟棄(workQueue隊列)最老的未被處理請求(隊列最先被放進去的任務(wù)),然后調(diào)用e.execute(r)重試執(zhí)行當(dāng)前任務(wù)(注意依然要走流程),除非執(zhí)行器關(guān)閉,在這種情況下任務(wù)被丟棄。

4.CallerRunsPolicy(調(diào)用方運行策略)
被拒絕任務(wù)的處理程序,它直接由提交任務(wù)的線程來運行這個提交的任務(wù),除非executor已關(guān)閉,在這種情況下任務(wù)被丟棄。

測試一下

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class Test {

    private static BlockingQueue blockingQueue = new ArrayBlockingQueue(5);

    private static ExecutorService executorService = new ThreadPoolExecutor(1, 5, 60, TimeUnit.SECONDS, blockingQueue, new ThreadPoolExecutor.AbortPolicy());

    /**
     * 主線程分配任務(wù),任務(wù)被拒絕執(zhí)行后暫停2秒,之后繼續(xù)分配任務(wù)
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i < 31; i++) {
            log.debug("第{}個任務(wù)", i);
            try {
                test(i);
            } catch (RejectedExecutionException e) {
                log.error("拒絕執(zhí)行{}", i);
                Thread.sleep(2000);
                log.debug("繼續(xù)執(zhí)行{}", i);
                test(i);
            }
        }
    }

    private static void test(final int index) {
        executorService.submit(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("InterruptedException", e);
            }
            log.debug("test run {}", index);
        });
        log.debug("隊列剩余空間:{}", blockingQueue.remainingCapacity());
    }
}

執(zhí)行結(jié)果
1、核心線程先初始化一個線程
2、第1個任務(wù)直接給線程
3、第2-6加入隊列,裝滿了
4、第7-10需創(chuàng)建線程用于執(zhí)行任務(wù)
5、到此隊列5個和線程五個一起最多處理10任務(wù),第11個任務(wù)拒絕處理,等待中...
6、繼續(xù)執(zhí)行,利用釋放的線程和隊列繼續(xù)處理(優(yōu)先使用線程,沒有加入隊列)...

"F:\Program Files\Java\jdk1.8.0_212\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.1\lib\idea_rt.jar=59703:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.1\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\Administrator\AppData\Local\Temp\classpath1401389501.jar org.jeecg.modules.Test
16:35:47.264 [main] DEBUG org.jeecg.modules.Test - 第1個任務(wù)
16:35:47.317 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:5
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 第2個任務(wù)
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 第3個任務(wù)
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:3
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 第4個任務(wù)
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:2
16:35:47.318 [main] DEBUG org.jeecg.modules.Test - 第5個任務(wù)
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:1
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 第6個任務(wù)
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 第7個任務(wù)
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 第8個任務(wù)
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 第9個任務(wù)
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 第10個任務(wù)
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:47.319 [main] DEBUG org.jeecg.modules.Test - 第11個任務(wù)
16:35:47.319 [main] ERROR org.jeecg.modules.Test - 拒絕執(zhí)行11
16:35:48.344 [pool-1-thread-1] DEBUG org.jeecg.modules.Test - test run 1
16:35:48.344 [pool-1-thread-2] DEBUG org.jeecg.modules.Test - test run 7
16:35:48.345 [pool-1-thread-3] DEBUG org.jeecg.modules.Test - test run 8
16:35:48.345 [pool-1-thread-4] DEBUG org.jeecg.modules.Test - test run 9
16:35:48.345 [pool-1-thread-5] DEBUG org.jeecg.modules.Test - test run 10
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 繼續(xù)執(zhí)行11
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 第12個任務(wù)
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:3
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 第13個任務(wù)
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:2
16:35:49.320 [main] DEBUG org.jeecg.modules.Test - 第14個任務(wù)
16:35:49.321 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:1
16:35:49.321 [main] DEBUG org.jeecg.modules.Test - 第15個任務(wù)
16:35:49.321 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:49.321 [main] DEBUG org.jeecg.modules.Test - 第16個任務(wù)
16:35:49.321 [main] ERROR org.jeecg.modules.Test - 拒絕執(zhí)行16
16:35:49.351 [pool-1-thread-2] DEBUG org.jeecg.modules.Test - test run 3
16:35:49.351 [pool-1-thread-4] DEBUG org.jeecg.modules.Test - test run 5
16:35:49.351 [pool-1-thread-3] DEBUG org.jeecg.modules.Test - test run 4
16:35:49.351 [pool-1-thread-5] DEBUG org.jeecg.modules.Test - test run 6
16:35:49.351 [pool-1-thread-1] DEBUG org.jeecg.modules.Test - test run 2
16:35:50.365 [pool-1-thread-2] DEBUG org.jeecg.modules.Test - test run 11
16:35:50.365 [pool-1-thread-4] DEBUG org.jeecg.modules.Test - test run 12
16:35:50.369 [pool-1-thread-5] DEBUG org.jeecg.modules.Test - test run 14
16:35:50.365 [pool-1-thread-3] DEBUG org.jeecg.modules.Test - test run 13
16:35:50.369 [pool-1-thread-1] DEBUG org.jeecg.modules.Test - test run 15
16:35:51.333 [main] DEBUG org.jeecg.modules.Test - 繼續(xù)執(zhí)行16
16:35:51.333 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:51.333 [main] DEBUG org.jeecg.modules.Test - 第17個任務(wù)
16:35:51.333 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:5
16:35:51.333 [main] DEBUG org.jeecg.modules.Test - 第18個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第19個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第20個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第21個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第22個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:3
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第23個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:2
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第24個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:1
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第25個任務(wù)
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:0
16:35:51.334 [main] DEBUG org.jeecg.modules.Test - 第26個任務(wù)
16:35:51.334 [main] ERROR org.jeecg.modules.Test - 拒絕執(zhí)行26
16:35:52.348 [pool-1-thread-5] DEBUG org.jeecg.modules.Test - test run 18
16:35:52.348 [pool-1-thread-3] DEBUG org.jeecg.modules.Test - test run 19
16:35:52.348 [pool-1-thread-2] DEBUG org.jeecg.modules.Test - test run 16
16:35:52.348 [pool-1-thread-1] DEBUG org.jeecg.modules.Test - test run 20
16:35:52.348 [pool-1-thread-4] DEBUG org.jeecg.modules.Test - test run 17
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 繼續(xù)執(zhí)行26
16:35:53.349 [pool-1-thread-1] DEBUG org.jeecg.modules.Test - test run 24
16:35:53.349 [pool-1-thread-4] DEBUG org.jeecg.modules.Test - test run 25
16:35:53.349 [pool-1-thread-2] DEBUG org.jeecg.modules.Test - test run 23
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:5
16:35:53.349 [pool-1-thread-5] DEBUG org.jeecg.modules.Test - test run 21
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 第27個任務(wù)
16:35:53.349 [pool-1-thread-3] DEBUG org.jeecg.modules.Test - test run 22
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 第28個任務(wù)
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 第29個任務(wù)
16:35:53.349 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:53.350 [main] DEBUG org.jeecg.modules.Test - 第30個任務(wù)
16:35:53.350 [main] DEBUG org.jeecg.modules.Test - 隊列剩余空間:4
16:35:54.353 [pool-1-thread-1] DEBUG org.jeecg.modules.Test - test run 27
16:35:54.353 [pool-1-thread-5] DEBUG org.jeecg.modules.Test - test run 29
16:35:54.353 [pool-1-thread-3] DEBUG org.jeecg.modules.Test - test run 30
16:35:54.353 [pool-1-thread-4] DEBUG org.jeecg.modules.Test - test run 26
16:35:54.353 [pool-1-thread-2] DEBUG org.jeecg.modules.Test - test run 28
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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