【Java 并发编程】线程池机制 ( 线程池阻塞队列 | 线程池拒绝策略 | 使用 ThreadPoolExecutor 自定义线程池参数 )
文章目錄
- 一、線程池阻塞隊列
- 二、拒絕策略
- 三、使用 ThreadPoolExecutor 自定義線程池參數
一、線程池阻塞隊列
線程池阻塞隊列是線程池創建的第 555 個參數 : BlockingQueue<Runnable> workQueue ;
public ThreadPoolExecutor(int corePoolSize, // 核心線程數 , 這些線程基本不會被銷毀int maximumPoolSize, // 最大線程數 , 線程池能創建的最大線程數量long keepAliveTime, // 空閑情況下 , 非核心線程存活時間TimeUnit unit, // 空閑時間單位BlockingQueue<Runnable> workQueue,// 任務的阻塞隊列 ★ThreadFactory threadFactory, // 創建線程的工廠類RejectedExecutionHandler handler) // 拒絕策略線程池阻塞隊列 : 線程池中的阻塞隊列 , 同一時刻 , 只能有 111 個線程訪問隊列 , 執行任務 入隊 / 出隊 操作 ; 隊列都是 FIFO 先進先出 ;
-
阻塞隊列相關概念 :
- 大小邊界 :
- 有界 : 阻塞隊列 大小有限制 , 不是無限大的 ;
- 無界 : 阻塞隊列 理論上無限大 , 比如設置成 Integer.MAX_VALUE ;
- 隊列已滿 : 只能出隊 , 不能入隊 ; 入隊操作需阻塞等待 ;
- 隊列為空 : 只能入隊 , 不能出隊 ; 出隊操作需要等待 ;
- 大小邊界 :
-
ArrayBlockingQueue : 有界阻塞隊列 , 需要 指定阻塞隊列大小 ;
-
LinkedBlockingQueue : 無界阻塞隊列 , 基于鏈表的阻塞隊列 ;
- Executors.newCachedThreadPool() 或 Executors.newFixedThreadPool(10) 方法創建的線程池 , 使用的是該阻塞隊列 ;
-
SynchronousQueue : 隊列 不存儲元素 , 后一個 Runnable 任務入隊 , 必須等到前一個任務執行完畢才可以 , 否則會一直阻塞等待 ;
- Executors.newCachedThreadPool() 方法創建的線程池 , 使用的是該阻塞隊列 ;
-
PriorityBlockingQueue : 有優先級的阻塞隊列 ;
阻塞隊列吞吐量 : SynchronousQueue > LinkedBlockingQueue > ArrayBlockingQueue ;
二、拒絕策略
線程池拒絕策略是線程池創建的第 777 個參數 : RejectedExecutionHandler handler ;
public ThreadPoolExecutor(int corePoolSize, // 核心線程數 , 這些線程基本不會被銷毀int maximumPoolSize, // 最大線程數 , 線程池能創建的最大線程數量long keepAliveTime, // 空閑情況下 , 非核心線程存活時間TimeUnit unit, // 空閑時間單位BlockingQueue<Runnable> workQueue,// 任務的阻塞隊列 ThreadFactory threadFactory, // 創建線程的工廠類RejectedExecutionHandler handler) // 拒絕策略 ★線程池拒絕策略 : 如果核心線程 , 非核心線程都在執行任務 , 阻塞隊列是有界的 , 也滿了 , 此時線程池如果再添加任務 , 就會觸發如下拒絕策略 ;
- DiscardPolicy : 丟棄任務 ;
- DiscardOldestPolicy : 丟棄隊頭的最舊的任務 ;
- AbortPolicy : 拋出異常 , 這也是默認方式 ;
- CallerRunsPolicy : 調用者自行處理 ;
線程池默認的拒絕策略是 拋出異常 方式 ;
private static final RejectedExecutionHandler defaultHandler =new AbortPolicy();三、使用 ThreadPoolExecutor 自定義線程池參數
創建 111 個線程池 , 核心線程數是 222 , 最大線程數是 333 , 則非核心線程 0 ~ 1 個 , 非核心線程最大空閑存活時間 60 秒 , 阻塞隊列最大存放 10 個元素 , 拒絕策略設置為拋出異常方式 , 如果阻塞隊列裝滿 , 再次嘗試執行新任務時 , 會拋出異常 ;
代碼示例 :
import java.util.concurrent.*;public class Main {public static void main(String[] args) {ExecutorService executorService = new ThreadPoolExecutor(2, // 核心線程數 23, // 最大線程數 3, 非核心線程 0 ~ 1 個60, // 非核心線程最大空閑存活時間 60 秒TimeUnit.SECONDS,new ArrayBlockingQueue<>(10), // 阻塞隊列, 最大存放 10 個元素Executors.defaultThreadFactory(), // 線程工廠new ThreadPoolExecutor.AbortPolicy() // 決絕策略, 如果執行任務失敗, 拋出異常);for (int i = 0; i < 20; i ++) {executorService.execute(new Task(i));}}static class Task implements Runnable {/*** 記錄線程的索引 0 ~ 99*/private int i = 0;public Task(int i) {this.i = i;}@Overridepublic void run() {System.out.println("線程 ID : " + Thread.currentThread().getName() + " , 線程索引 : " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}} }執行結果 : 這里線程最大執行到了 121212 , 也就是從 000 開始計數 , 執行了 131313 個任務 , 其中 333 個線程池各自執行一個任務 , 阻塞隊列存放 101010 個任務 , 再次嘗試將第 141414 個任務放入阻塞隊列時 , 報出 java.util.concurrent.RejectedExecutionException 異常 , 但是隊列中的 101010 個任務也正常執行完畢 ;
線程 ID : pool-1-thread-2 , 線程索引 : 1 線程 ID : pool-1-thread-3 , 線程索引 : 12 線程 ID : pool-1-thread-1 , 線程索引 : 0 Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task Main$Task@5cad8086 rejected from java.util.concurrent.ThreadPoolExecutor@6e0be858 [Running, pool size = 3, active threads = 3, queued tasks = 10, completed tasks = 0]at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)at Main.main(Main.java:16) 線程 ID : pool-1-thread-3 , 線程索引 : 2 線程 ID : pool-1-thread-1 , 線程索引 : 4 線程 ID : pool-1-thread-2 , 線程索引 : 3 線程 ID : pool-1-thread-1 , 線程索引 : 5 線程 ID : pool-1-thread-2 , 線程索引 : 7 線程 ID : pool-1-thread-3 , 線程索引 : 6 線程 ID : pool-1-thread-1 , 線程索引 : 9 線程 ID : pool-1-thread-2 , 線程索引 : 8 線程 ID : pool-1-thread-3 , 線程索引 : 10 線程 ID : pool-1-thread-2 , 線程索引 : 11總結
以上是生活随笔為你收集整理的【Java 并发编程】线程池机制 ( 线程池阻塞队列 | 线程池拒绝策略 | 使用 ThreadPoolExecutor 自定义线程池参数 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java 并发编程】线程池机制 ( T
- 下一篇: 【Java 并发编程】线程池机制 ( 线