前言
做的學習筆記,並加入了自己的理解,謝謝
使用線程池的原因
我們創建的線程在運行結束後都會被虛擬機銷燬,如果線程數量多的話,頻繁的創建和銷燬線程會大大浪費時間和效率,更重要的是浪費內存,線程池可以讓線程運行後不立刻銷燬,而是讓線程重複使用,繼續執行其他任務
線程池的優化
- 降低資源消耗
- 提高響應速度
- 提高線程的可管理性
流程圖
線程池的核心參數
/**
* 線程核心參數
* @param corePoolSize 核心線程數量
* @param maximumPoolSize 最大線程數量
* @param keepAliveTime 線程空間後的存活時間
* @param unit 時間單位
* @param workQueue 用於存放任務的阻塞隊列
* @param threadFactory 線程工廠類
* @param handler 當隊列和最大線程池都滿了之後的飽和策略
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
線程池可選擇的阻塞隊列
- 無界隊列
- 有界隊列
如果超出界定值,將阻塞 put 方法
- 同步移交隊列
也就是隊列不存儲元素,每個插入操作都要等待另一個線程調用移出操作,否則插入操作一直處於阻塞
無界隊列
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>();
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("向隊列中添加值:" + i);
}
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("向隊列中添加值:" + i);
}
有界隊列
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("向隊列中添加值:" + i);
}
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(5);
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("向隊列中添加值:" + i);
}
同步移交隊列
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
for (int i = 0; i < 10; i++) {
// 阻塞在這裏
queue.put(i);
System.out.println("向隊列中添加值:" + i);
}
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
// 插入值
new Thread(() -> {
try {
queue.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 取值
new Thread(() -> {
try {
Integer value = queue.take();
System.out.println("取到值:" + value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
線程池可選擇的飽和策略
類 | 說明 |
---|---|
AbortPolicy | 丟棄任務並拋出RejectedExecutionException異常 《默認》 |
DiscardPolicy | 拋棄策略,但是不拋出異常 |
DiscardOldestPolicy | 丟棄隊列最前面的任務(舊任務),然後重新嘗試執行任務 |
CallerRunsPolicy | 由調用線程處理該任務 |
常用線程池
線程數量無限的線程池
ExecutorService pool = Executors.newCachedThreadPool();
public class Executors {
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
}
線程數量固定線程池
ExecutorService pool = Executors.newFixedThreadPool(5);
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
單一線程線程池
ExecutorService pool = Executors.newSingleThreadExecutor();
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
提交任務
submit,獲取結果
ExecutorService threadPool = Executors.newCachedThreadPool();
// 提交任務,並獲取結構
Future<Integer> future = threadPool.submit(() -> {
Thread.sleep(3000L);
return 2 * 5;
});
// 阻塞獲取結果
Integer value = future.get();
System.out.println("執行結果:" + value);
execute,沒有結果
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.execute(() -> {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 計算結果
Integer num = 2 * 3;
System.out.println("執行結果:" + num);
});