文章目錄
在上文中已經寫過Executor線程調度框架的使用及幾種線程池,它們是整個Java併發編程的核心內容;本文將繼續講解和Executor一樣重要的自定義線程池,它能讓我們自己去定義一個多線程的執行者擁有的線程核心數、最大線程數、空閒線存活時間等。
本篇總結自《Java併發編程實踐》第八章 應用線程池 ,以及相關博客,想要更加深入瞭解的同學建議閱讀該書。
一、什麼是ThreadPoolExecutor
ThreadPoolExecutor位於java.util.concurrent併發包下,爲一些Executor提供了基本的實現,在JDK1.5中由Executors中的工廠中的newCachedThreadPool、newFixedThreadPool和newScheduledThreadExecutor方法所返回。但在JDK1.7之後,不能通過Executors去獲得ThreadPoolExecutor了,而是需要自己手動去定製。ThreadPoolExecutor是一個靈活的、健壯的池實現,允許用戶進行各種各樣的定製。
二、ThreadPoolExecutor構造方法參數
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,//可不設置
RejectedExecutionHandler handler//可不設置)
- core線程還能應付的,則不斷的創建新的線程,但不會超出corePoolSize;
- core線程無法應付,則將任務扔到隊列裏面,並且用core線程去執行;
- 工作隊列滿了(意味着插入任務失敗),則開始創建MAX線程,線程數達到MAX後,隊列還一直是滿的,則拋出RejectedExecutionException。
2.1、corePoolSize
核心線程池大小,當線程池中的線程數目小於corePoolSize時,新提交任務將創建一個新線程執行任務,即使此時線程池中存在空閒線程。
2.1、maximumPoolSize
最大線程池大小,表示當前池中可以活躍的最大線程數目。
2.3、keepAliveTime
線程池中超過corePoolSize數目的空閒線程最大存活時間。
2.4、TimeUnit
keepAliveTime時間單位。可以設置爲TimeUnit.MICROSECONDS
、TimeUnit.SECONDS
等單位,分別表示毫秒和秒。
2.5、workQueue
阻塞任務隊列,用以存儲超出了corePoolSize的線程。
2.6、threadFactory
新建線程工廠。如果沒有的話則使用系統默認的。
2.7、RejectedExecutionHandler
當提交任務數超過maxmumPoolSize與workQueue之和時,任務會交給RejectedExecutionHandler來處理。如果沒有的話則使用系統默認的。
三、使用自己構造的ThreadPoolExecutor
測試類:
public class ThreadPoolExecutorDemo {
@Test
public void testThreadPoolExecutor(){
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
10,
1000,
TimeUnit.MICROSECONDS,
new ArrayBlockingQueue<Runnable>(3),
new MyThreadFactory(),
new MyRejectedExecutionHandler());
for (int i = 0; i < 35; i++) {
int count = i;
executor.execute(new Runnable() {
@Override
public void run() {
//模擬耗時操作
for (int j = 0; j < 500000; j++) {
//..
}
System.out.println("這是第"+count+"個線程在執行任務----"+Thread.currentThread().getName());
}
});
}
}
}
自定義的線程工廠類:
public class MyThreadFactory implements ThreadFactory {
//線程標識器
private AtomicInteger count = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
//標識器自增1
count.incrementAndGet();
Thread thread = new Thread(r, "自定義線程(" + count + ")");
return thread;
}
}
自定義的異常處理類:
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//對超出的線程任務進行處理
System.out.println("已處理...");
}
}
執行後發現,當循環過多時,需要同時活躍的線程大於5個之後,新產生的線程進入阻塞隊列中,當需要同時活躍的線程大於10個之後,新產生的線程將被自定義的MyRejectedExecutionHandler 處理。