在 Java 中,若每個請求到達就創建新線程,開銷極大:線程創建與銷毀消耗大量系統資源與時間,甚至超過處理業務邏輯的開銷。活躍線程佔用內存與 CPU 時間片,若 JVM 內線程過多,會導致內存耗盡或「上下文切換過度」,引發系統資源不足。
線程池通過 池化技術 解決兩大核心問題:
額外收益:請求到達時線程已就緒,消除創建延遲,響應更快;通過調整池大小動態適應負載。
一個標準線程池至少包含四大組件:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue workQueue,
RejectedExecutionHandler handler)
corePoolSize:核心線程數(含空閒)maximumPoolSize:最大線程數keepAliveTime + unit:非核心線程空閒存活時間workQueue:任務緩衝隊列handler:拒絕策略corePoolSize,創建新線程執行(即使有空閒線程);corePoolSize 且 workQueue 未滿,任務入隊;corePoolSize 且 workQueue 滿且線程數 < maximumPoolSize,創建新線程執行;maximumPoolSize 且 workQueue 滿,執行拒絕策略;keepAliveTime 將被回收,動態調整池大小。優先級順序:核心線程 → 任務隊列 → 最大線程 → 拒絕策略。
public class ThreadTest {
public static void main(String[] args) {
List strList = new ArrayList<>();
for (int i = 0; i < 100; i++) strList.add("String" + i);
int threadNum = Math.min(strList.size(), 5);
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, threadNum, 300, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue(3),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i = 0; i < threadNum; i++) {
executor.execute(new PrintStringThread(i, strList, threadNum));
}
executor.shutdown();
}
}
class PrintStringThread implements Runnable {
private int num;
private List strList;
private int threadNum;
public PrintStringThread(int num, List strList, int threadNum) {
this.num = num;
this.strList = strList;
this.threadNum = threadNum;
}
@Override
public void run() {
int length = 0;
for (String str : strList) {
if (length % threadNum == num) {
System.out.println("線程編號:" + num + ",字符串:" + str);
}
length++;
}
}
}
思考點:上述代碼有潛在缺陷(如任務分配邏輯、隊列大小與線程數關係),留待讀者分析。
ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
poolTaskExecutor.setQueueCapacity(200); // 隊列容量
poolTaskExecutor.setCorePoolSize(5); // 核心線程數
poolTaskExecutor.setMaxPoolSize(1000); // 最大線程數
poolTaskExecutor.setKeepAliveSeconds(30000); // 空閒存活秒數
poolTaskExecutor.initialize();
<bean id="poolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 核心線程數,默認 1 -->
<property name="corePoolSize" value="5" />
<!-- 最大線程數,默認 Integer.MAX_VALUE -->
<property name="maxPoolSize" value="50" />
<!-- 隊列最大長度 -->
<property name="queueCapacity" value="2000" />
<!-- 空閒存活時間,默認 60s -->
<property name="keepAliveSeconds" value="100" />
<!-- 拒絕策略:AbortPolicy(拋異常) / CallerRunsPolicy(調用者執行) -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
Spring 的 ThreadPoolTaskExecutor 封裝了 ThreadPoolExecutor,提供更友好的配置體驗,支持與 Spring 生命周期綁定,推薦在 Spring 項目中使用。
corePoolSize;監控隊列積壓、拒絕次數、線程存活情況;合理選擇拒絕策略(CallerRunsPolicy 可平滑降級)。線程池是 Java 高併發編程的基石。掌握 ThreadPoolExecutor 七大參數交互邏輯、理解 Spring 封裝的配置映射、根據業務特性合理規劃池參數,是構建穩定、高效後端系統的必修課。