![](https://news.xinpengboligang.com/upload/keji/b7aefb8fde314a708904a6eb65f62e6f.jpeg)
線程池高手進階:揭秘ThreadPoolExecutor的小妙招! - 程序員古德
RejectedExecutionHandler總結
ThreadPoolExecutor 是 Java 中用於創建和管理線程池的接口,當線程池中的任務隊列已滿,並且線程池中的線程數量已經達到最大時,如果再有新的任務提交,就需要一個策略來處理這些無法執行的任務。它 提供了四種拒絕策略,都是 RejectedExecutionHandler 接口的實現,如下:
- AbortPolicy(默認策略):直接拋出一個 RejectedExecutionException 異常。
- CallerRunsPolicy:調用執行任務的 execute 方法的線程來運行任務,如果執行程序已經關閉,那麼任務將被拋棄。
- DiscardPolicy:無法執行的任務將被拋棄,不會拋出任何異常。
- DiscardOldestPolicy:如果執行程序尚未關閉,則位於工作隊列頭部的任務將被刪除,然後重試執行任務(如果再次失敗,則重復此過程)。
以下是使用ThreadPoolExecutor的代碼示例,如下:
import java.util.concurrent.*;
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
// 創建一個固定大小的線程池
int corePoolSize = 2;
int maximumPoolSize = 4;
long keepAliveTime = 10L;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
// 使用不同的拒絕策略
RejectedExecutionHandler abortPolicy = new ThreadPoolExecutor.AbortPolicy();
RejectedExecutionHandler callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
RejectedExecutionHandler discardPolicy = new ThreadPoolExecutor.DiscardPolicy();
RejectedExecutionHandler discardOldestPolicy = new ThreadPoolExecutor.DiscardOldestPolicy();
// 創建線程池並設置拒絕策略
ThreadPoolExecutor executor1 = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, abortPolicy);
ThreadPoolExecutor executor2 = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, callerRunsPolicy);
ThreadPoolExecutor executor3 = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, discardPolicy);
ThreadPoolExecutor executor4 = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, discardOldestPolicy);
// 提交任務
for (int i = 0; i < 10; i ) {
final int taskId = i;
executor1.execute(() -> System.out.println("Executing task " taskId " with AbortPolicy"));
executor2.execute(() -> System.out.println("Executing task " taskId " with CallerRunsPolicy"));
executor3.execute(() -> System.out.println("Executing task " taskId " with DiscardPolicy"));
executor4.execute(() -> System.out.println("Executing task " taskId " with DiscardOldestPolicy"));
}
}
}
在上面的代碼示例中,由於工作隊列和線程池的大小都設置得很小,所以提交的任務會很快填滿隊列和線程池,從而觸發拒絕策略,不同的拒絕策略適用於不同的場景,在實際應用中,應該根據具體需求來合理設置線程池的大小、工作隊列的容量以及拒絕策略。
ThreadFactory總結
ThreadFactory接口常用於在ThreadPoolExecutor中管理控制線程的名稱、優先級、是否守護線程以及其他線程屬性。下面是一個簡單的ThreadFactory使用案例,案例中定義了一個CustomThreadFactory類,如下代碼:
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class CustomThreadFactory implements ThreadFactory {
private final String prefix;
private final AtomicInteger threadNumber = new AtomicInteger(1);
public CustomThreadFactory(String prefix) {
this.prefix = prefix;
}
@Override
public Thread newThread(Runnable r) {
// 創建一個新線程
Thread thread = new Thread(r);
// 設置線程名稱,使用前綴和遞增的數字
thread.setName(prefix "-" threadNumber.getAndIncrement());
// 可以設置其他屬性,比如優先級、守護狀態等
// thread.setPriority(Thread.MAX_PRIORITY);
// thread.setDaemon(false);
return thread;
}
}
在上面代碼中:
- CustomThreadFactory類實現了ThreadFactory接口,並重寫了newThread方法。
- 構造函數接受一個prefix參數,用於生成線程名稱的前綴。
- 使用AtomicInteger來生成唯一的線程編號,確保在多線程環境下編號不會重復。
- 在newThread方法中,創建一個新的Thread對象,並通過setName方法設置線程的名稱,這裡使用前綴和遞增的編號來構建線程名稱,方便在日志或調試時識別線程。
- 還可以根據需要調用其他Thread方法來設置線程的優先級、守護狀態等屬性。
如下是CustomThreadFactory的使用方法,如下:
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.SynchronousQueue;
public class ThreadPoolExample {
public static void main(String[] args) {
// 創建一個具有自定義線程工廠的線程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize
10, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS, // unit for keepAliveTime
new SynchronousQueue<>(), // workQueue
new CustomThreadFactory("CustomThreadPool-") // 自定義線程工廠
);
// 提交任務給線程池
for (int i = 0; i < 20; i ) {
final int taskId = i;
executor.submit(() -> {
// 執行任務
System.out.println("Task " taskId " is running on thread " Thread.currentThread().getName());
});
}
// 關閉線程池(這通常是在應用程序關閉時完成的)
// executor.shutdown();
}
}
![](https://news.xinpengboligang.com/upload/keji/4b50fc7b48d25ed9901d72470c26ae59.jpeg)
關註我,每天學習互聯網編程技術 - 程序員古德
END!