線程池的作用
線程的流程和原理
線程池的創建
線程學習的第二篇學習講過線程池的創建,使用的是google的guava
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
Java提供的線程池
這裏是使用java先使用java自帶的幾種創建線程池的方式,直接看demo:
private static void initThreadPool() {
// 一個線程池,5個工作線程
// ExecutorService threadPool = Executors.newFixedThreadPool(5);
// 一個線程池,1個工作線程
// ExecutorService threadPool = Executors.newSingleThreadExecutor();
// 時間調度,可做定時
// ExecutorService threadPool = Executors.newScheduledThreadPool(5);
// ExecutorService threadPool = Executors.newWorkStealingPool();
// 一個線程池, N個工作線程
ExecutorService threadPool = Executors.newCachedThreadPool();
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t辦理業務");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
上面demo中有五種java提供的線程池,都能正常使用,但是不推薦這樣子做,阿里巴巴規範手冊裏面也不推薦這種做法,看看源碼就知道了:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
這裏的默認最大線程數Integer最大值,很容易造成錯誤操作導致的線程積壓,最後會導致OOM,詳細的規範和其他需要注意的地方可以參考阿里巴巴開發手冊。
根據這段代碼我們可以看出其底層使用的是:
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
其他幾種創建方式也是如此,可以點擊源碼參閱,這裏就不粘貼了。
根據這個我們便可知道,我們可以自己手動創建線程池;
自定義創建線程池
public static void main(String[] args) {
// 查看自己電腦上的核心線程數
System.out.println(Runtime.getRuntime().availableProcessors());
ExecutorService threadPool = new ThreadPoolExecutor(2,
5,
2L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "\t辦理業務");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
// initThreadPool();
}
可以自行跑一下代碼,看結果,多測幾個臨界值(7、8、9);
這些參數的意思:
主要講下第7個參數,handler,主要分爲四種:
線程滿了之後的策略:
- AbortPolicy:直接拋出RejectedExecutionException異常,組織系統正常運行
- CallerRunsPolicy: "調用者運行"一種調節機制,該策略既不會拋棄任務,也不會拋出異常,而是將某些任務回退到調用者,從而降低新任務的流量
- DiscardOldestPolicy: 拋棄隊列中等待最久的任務,然後把當前任務加入隊列中嘗試在次提交當前任務
- DiscardPolicy: 默默丟棄無法處理的任務,不予任何處理,也不拋出異常。如果允許任務丟失,這就是最好的策略
可以參考源碼:
public static class CallerRunsPolicy implements RejectedExecutionHandler{
...
}
public static class AbortPolicy implements RejectedExecutionHandler{
...
}
...
謝謝大家閱讀!!