java并发之线程池
生活随笔
收集整理的這篇文章主要介紹了
java并发之线程池
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- @[TOC]
- 1:ThreadPoolExcutor
- (1):ThreadPoolExcutor構造函數
- (2):構造函數的參數
- (3):圖示 核心線程數 最大線程數 阻塞隊列
- (4):一個任務在線程池的流程
- 2:固定容量的線程池(newFixedThreadPool)
- (1):構造函數
- (2):特點
- (3):代碼示例
- 3:可緩存的線程池
- (1):構造函數
- (2):特點
- 4:單線程池
- (1):構造函數
- (2):特點
- 5:固定數量線程池...和ThreadPoolExecutor的區別聯系
- (1)如何創建固定數量的線程池,可緩存的線程池,單線程池
- (2)和ThreadPoolExcutor的聯系
- 5:自定義線程池
- (1):自定義線程池的規則
- (2):關于線程池的 Executor工具類的execute()方法
- (3):代碼示例
- (4):關于拒絕策略
- 6:關閉線程池
- @[TOC]
- 1:ThreadPoolExcutor
- (1):ThreadPoolExcutor構造函數
- (2):構造函數的參數
- (3):圖示 核心線程數 最大線程數 阻塞隊列
- (4):一個任務在線程池的流程
- 2:固定容量的線程池(newFixedThreadPool)
- (1):構造函數
- (2):特點
- (3):代碼示例
- 3:可緩存的線程池
- (1):構造函數
- (2):特點
- 4:單線程池
- (1):構造函數
- (2):特點
- 5:固定數量線程池...和ThreadPoolExecutor的區別聯系
- (1)如何創建固定數量的線程池,可緩存的線程池,單線程池
- (2)和ThreadPoolExcutor的聯系
- 5:自定義線程池
- (1):自定義線程池的規則
- (2):關于線程池的 Executor工具類的execute()方法
- (3):代碼示例
- (4):關于拒絕策略
- 6:關閉線程池
1:ThreadPoolExcutor
(1):ThreadPoolExcutor構造函數
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);}(2):構造函數的參數
- corePoolSize核心線程數目(最多保留的線程數)
- maximumPoolSize最大線程數目
- keepAliveTime生存時間-針對救急線程
- unit時間單位-針對救急線程
- workQueue阻塞隊列
- threadFactory線程工廠-可以為線程創建時起個好名字
- handler拒絕策略
(3):圖示 核心線程數 最大線程數 阻塞隊列
- 核心線程數就是我們銀行一直正常開的窗口
- 阻塞隊列就是銀行常用窗口人數滿了,然后就在后候客區等待的顧客
- 救急線程就是阻塞隊列滿了 不得不再開幾個營業窗口
- 最大線程數目 = 救急線程數目 + 核心線程數目
(4):一個任務在線程池的流程
- 線程池中剛開始沒有線程,當一個任務提交給線程池后,線程池會創建一個新線程來執行任務。
- 當線程數達到corePoolSize并沒有線程空閑,這時再加入任務,新加的任務會被加入workQueue隊列排
隊,直到有空閑的線程。 - 如果隊列選擇了有界隊列,那么任務超過了隊列大小時,會創建maximumPoolSize-corePoolSize數目的
線程來救急。 - 如果線程到達maximumPoolSize仍然有新任務這時會執行拒絕策略。拒絕策略jd提供了4種實現,其它
著名框架也提供了實現- AbortPolicy讓調用者拋出RejectedExecutionException異常,這是默認策略
- CallerRunsPolicy讓調用者運行任務
- DiscardPolicy放棄本次任務
- DiscardOldestPolicy放棄隊列中最早的任務,本任務取而代之
- Dubbo的實現,在拋出RejectedExecutionException異常之前會記錄日志,并dump線程棧信息,方便定
位問題 - Netty的實現,是創建一個新線程來執行任務
- ActiveMQ的實現,帶超時等待(60s)嘗試放入隊列,類似我們之前自定義的拒絕策略
- PinPoint的實現,它使用了一個拒絕策略鏈,會逐一嘗試策略鏈中每種拒絕策略
- 當高峰過去后,超過corePoolSize的救急線程如果一段時間沒有任務做,需要結束節省資源,這個時間由
- keepAliveTime和unit來控制。
2:固定容量的線程池(newFixedThreadPool)
(1):構造函數
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}(2):特點
- 核心線程數==最大線程數
(沒有救急線程被創建),因此也無需超時時間 - 阻塞隊列是無界的,可以放任意數量的任務
- 評價
適用于任務量已知,相對耗時的任務
(3):代碼示例
public class text02 {public static void main(String[] args) {ExecutorService executorService1 = Executors.newFixedThreadPool(2);//固定線程數 核心線程數 == 最大線程數 無救急線程 并且線程不會關閉//線程池里開啟一個線程 并執行一個任務executorService1.execute(() -> {System.out.println(Thread.currentThread().getName() + "->1");});//線程池再開啟一個線程 并執行一個任務executorService1.execute(() -> {System.out.println(Thread.currentThread().getName() + "->2");});//此時又來了一個任務,因為前面的任務執行時間比較短,所以再來任務的話,不會進入阻塞隊列//而是會用前面已經開啟的線程繼續執行任務executorService1.execute(()-> {System.out.println(Thread.currentThread().getName()+"->3");});} }3:可緩存的線程池
(1):構造函數
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());(2):特點
- 核心線程數為0,最大線程數為Interger.MAX_VALUE,救急線程的空閑存活時間是60s
- 沒有核心線程 全部都是救急線程
- 救急線程可以無線創建
- 隊列采用了SynchronousQueue實現特點是,它沒有容量,沒有線程來取是放不進去的(一手交錢、一手
交貨) - 評價
整個線程池表現為線程數會根據任務量不斷增長,沒有上限,當任務執行完畢,空閑1分鐘后釋放線
程。==適合任務數處比較密集,但每個任務執行時間較短的情況 ==(如果任務時間比較長,那么就會不斷創建線程,消耗系統性能)
4:單線程池
(1):構造函數
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}(2):特點
- 核心線程數為1,最大線程數也為1,這個線程一直存活,不會釋放
- 隊列是無界隊列,當任務數目大于1的時候,任務會被放入無界隊列
- 和普通單線程的區別
自己創建一個單線程串行執行任務,如果任務執行失敗而終止那么沒有任何補救措施,而線程池還會新建
一個線程,保證池的正常工作 - 和固定容量的線程池只開辟一個線程的區別
Executors…newSingleThreadExecutor()線程個數始終為1,不能修改
FinalizableDelegatedExecutorService應用的是裝飾器模式,只對外暴露了ExecutorService接口,因此不
能調用ThreadPoolExecutor中特有的方法
Executors.newFixedThreadPool(1)初始時為l,以后還可以修改
對外暴露的是ThreadPoolExecutor對象,可以強轉后調用setCorePoolSize等方法進行修改
5:固定數量線程池…和ThreadPoolExecutor的區別聯系
(1)如何創建固定數量的線程池,可緩存的線程池,單線程池
ExecutorService executorService1 = Executors.newFixedThreadPool(5);ExecutorService executorService2 = Executors.newSingleThreadExecutor();ExecutorService executorService3 = Executors.newCachedThreadPool();(2)和ThreadPoolExcutor的聯系
我們將對應的線程池點進去,發現其實底層還是靠ThreadPoolExcutors來實現
5:自定義線程池
(1):自定義線程池的規則
我們采用 ThreadPoolExcutors來創建,這使阿里爸爸開發手冊中明文推薦的,主要是其他線程池實現類都有OOM(內存用完了)的風險
(2):關于線程池的 Executor工具類的execute()方法
- 當有新的任務要處理時,先看線程池中的線程數量是否大于corePoolSize,再看緩沖隊列workQueue是否滿,最后看線程池 中的線程數量是否大于maximumPoolSize
另外,當線程池中的線程數量大于corePoolSize時,如果里面有線程的空閑時間超過了keepAliveTime,就將其移除線程池 - 也就是excutor()方法中會創建線程執行任務,但是這個線程的數量是有限的,雖然數量有限,但是核心線程可以重復執行任務,救急線程在空閑存活時間的里也可以執行任務
(3):代碼示例
public class text03 {public static void main(String[] args) {Executors.newCachedThreadPool();ThreadPoolExecutor pool = new ThreadPoolExecutor(2,//核心線程數5,//最大線程數 = 核心線程數 + 救急線程數(當阻塞隊列)3,//救濟線程的空閑存活時間TimeUnit.MINUTES,//時間的單位new LinkedBlockingQueue<>(3),//阻塞隊列默認為無界隊列但是我將其設置為3Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()//拒絕策略,一旦超過最大線程數就拋異常);//我們在一個for循環內//當我們同時來了9個任務的時候,會有2個任務去核心線程去執行,還有3個任務進入阻塞隊列,還有3個任務會去救急線程那去執行//那么我們的還有一個線程無法執行,此時會采取拒絕策略 ;//我們阻塞隊列中的任務是等著 救急線程 或者 核心線程去執行完手里的任務去執行的for (int i = 1; i <= 9; i++) {pool.execute(()->{System.out.println(Thread.currentThread().getName()+"--->"+"ok");});}} }(4):關于拒絕策略
- new ThreadPoolExecutor.AbortPolicy() 這個是默認的拒絕策略 是拋出異常的
- new ThreadPoolExecutor.CallerRunsPolicy() 這個是讓調用者去執行這個任務
- new ThreadPoolExecutor.DiscardPolicy() 這個是直接丟掉任務 不拋異常
- new ThreadPoolExecutor.DiscardOldestPolicy() 丟掉最早執行的任務 然后再執行本任務
6:關閉線程池
總結
以上是生活随笔為你收集整理的java并发之线程池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 往国外汇款怎么汇?
- 下一篇: Win10屏幕刷新率怎么调