1.使用線程池的優點
1.減少資源的消耗。重複利用已經建立的線程,避免頻繁的創造和銷毀線程,減少消耗。
2.提高響應速度。當執行任務時,不需要去建立線程再來執行,隻要調動現有的線程來執行即可。
3.提高了線程的管理性。線程是稀缺資源,使用線程池可以進行統一的配置設定、調優和監控。
2.建立線程池的兩種方案
1.通過Executors建立,它提供了四種線程池:
newCachedThreadPool建立一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則建立線程。
newFixedThreadPool 建立一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
newScheduledThreadPool 建立一個定長線程池,支援定時及周期性任務執行。
newSingleThreadExecutor 建立一個單線程化的線程池,它隻會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
注意:不建議使用這種方法建立線程池。因為newFixedThreadPool 和newSingleThreadExecutor允許的最大請求隊列長度為Integer.MAX_VALUE,可能會堆積大量的請求,進而導緻OOM。newCachedThreadPoo和newScheduledThreadPool允許的建立線程的最大數量為Integer.MAX_VALUE,,進而導緻OOM。
public class Demo01 {
public static void main(String[] args) {
//ExecutorService threadPool = Executors.newSingleThreadExecutor(); //建立單個線程
//ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);//建立一個固定大小的線程池
//ExecutorService threadPool = Executors.newFixedThreadPool(5); //建立一個固定大小的線程池
ExecutorService threadPool = Executors.newCachedThreadPool(); //建立大小可伸縮的線程池
try {
for (int i = 0; i < 30; i++) {
//使用線程池來建立線程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown(); //線程池使用完畢後需要關閉
}
}
}
2.通過ThreadPoolExecutor建立,new ThreadPoolExecutor有7個核心參數,分别如下:其最後一個參數拒絕政策共有四種:ThreadPoolExecutor(int corePoolSize, //核心線程池大小,始終存在 int maximumPoolSize, //最大線程數 long keepAliveTime, //空閑線程等待時間,逾時則銷毀 TimeUnit unit, //時間機關 BlockingQueue<Runnable> workQueue, //等待阻塞隊列 ThreadFactory threadFactory, //線程工廠 RejectedExecutionHandler handler) //線程拒絕政策
//new ThreadPoolExecutor.AbortPolicy():達到最大承載量,不再處理,并且抛出異常 //new ThreadPoolExecutor.CallerRunsPolicy():達到最大承載量,從哪來的去哪裡 //new ThreadPoolExecutor.DiscardPolicy():達到最大承載量,丢掉任務,但不抛出異常 //new ThreadPoolExecutor.DiscardOldestPolicy():達到最大承載量,嘗試與最早執行的線程去競争,不抛出異常
public class Demo02 {
public static void main(String[] args) {
//new ThreadPoolExecutor.AbortPolicy():達到最大承載量,不再處理,并且抛出異常
//new ThreadPoolExecutor.CallerRunsPolicy():達到最大承載量,從哪來的去哪裡
//new ThreadPoolExecutor.DiscardPolicy():達到最大承載量,丢掉任務,但不抛出異常
//new ThreadPoolExecutor.DiscardOldestPolicy():達到最大承載量,嘗試與最早執行的線程去競争,不抛出異常
//最大線程池大小該如何定義
//1.cpu密集型,邏輯處理器個數
//2.io密集型 > 判斷程式十分耗IO的線程,最大線程池大小應該比這個大
int maxPools= Runtime.getRuntime().availableProcessors();
System.out.println(maxPools);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,
maxPools,
3,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 0; i < 10; i++) {
//使用線程池來建立線程
//最大承載:maximumPoolSize+workQueue,超過執行拒絕政策
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown(); //線程池使用完畢後需要關閉
}
}
}