前言
這周我投遞出了簡歷,崗位是java後端開發工程師。這周美團面試官給我進行了面試。面試過程當中他問了線程池,今天詳細講一講Java線程池。java
線程池
線程池維護着多個線程,等待着監督管理者分配可併發執行的任務。這避免了在處理短期任務時建立與銷燬線程的代價。面試
1start()建立必定數量的線程池,進行線程循環 2 3stop()中止全部線程循環,回收全部資源 4 5addTask()添加任務
Excutors建立線程池便捷方法以下:後端
1Executors.newFixedThreadPool(100);//建立固定大小的線程池 2Executors.newSingleThreadExecutor();//建立只有一個線程的線程池 3Executors.newCachedThreadPool();//建立一個不限線程數上限的線程池,任何提交的任務都將當即執行
對於服務端須要長期運行的程序,建立線程池應該使用ThreadPoolExecutor
的構造方法緩存
1public ThreadPoolExecutor( 2 int corePoolPoolSize,//線程池長期維持的線程數 3 int maximumPoolSize, //線程數的上限 4 long keepAliveTime,//空閒線程存活時間 5 TimeUnit unit,//時間單位 6 BlockingQueue<Runnable> workQueue,//任務的排隊隊列 7 ThreadFactory threadFactory,//新線程的產生方式 8 RejectedExecutionHandler handler//拒絕策略 9 )
java線程池有7大參數,4大特性。服務器
特性一:當池中正在運行的線程數(包括空閒線程)小於corePoolSize時,新建線程執行任務。多線程
特性二:當池中正在運行的線程數大於等於corePoolSize時,新插入的任務進入workQueue排隊(若是workQueue長度容許),等待空閒線程來執行。併發
特性三:當隊列裏的任務數達到上限,而且池中正在運行的線程數小於maximumPoolSize,對於新加入的任務,新建線程。less
特性四:當隊列裏的任務數達到上限,而且池中正在運行的線程數等於maximumPoolSize,對於新加入的任務,執行拒絕策略(線程池默認的拒絕策略是拋異常)。spa
種類
newCachedThreadPool操作系統
- 核心線程數爲0,最大線程數爲
Integer.MAX_VALUE
1public static ExecutorService newCachedThreadPool() { 2 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 3 60L, TimeUnit.SECONDS, 4 new SynchronousQueue<Runnable>()); 5 }
做用
建立一個可根據須要建立新線程的線程池,可是在之前構造的線程可用時將重用它們,並在須要時使用提供的 ThreadFactory 建立新線程。
特徵
(1)線程池中數量沒有固定,可達到最大值(Interger. MAX_VALUE)
(2)線程池中的線程可進行緩存重複利用和回收(回收默認時間爲1分鐘)
(3)當線程池中,沒有可用線程,會從新建立一個線程
建立方式
Executors.newCachedThreadPool();
newFixedThreadPool
- 核心線程數與最大線程數均爲指定的nThreads
- 空閒線程的存活時間是0
- 工做隊列是無界隊列
1public static ExecutorService newFixedThreadPool(int nThreads) { 2 return new ThreadPoolExecutor(nThreads, nThreads, 3 0L, TimeUnit.MILLISECONDS, 4 new LinkedBlockingQueue<Runnable>()); 5 }
做用
建立一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。在任意點,在大多數 nThreads 線程會處於處理任務的活動狀態。若是在全部線程處於活動狀態時提交附加任務,則在有可用線程以前,附加任務將在隊列中等待。若是在關閉前的執行期間因爲失敗而致使任何線程終止,那麼一個新線程將代替它執行後續的任務(若是須要)。在某個線程被顯式地關閉以前,池中的線程將一直存在。
特徵
(1)線程池中的線程處於必定的量,能夠很好的控制線程的併發量
(2)線程能夠重複被使用,在顯示關閉以前,都將一直存在
(3)超出必定量的線程被提交時候需在隊列中等待
建立方式
1(1)Executors.newFixedThreadPool(int nThreads);//nThreads爲線程的數量 2(2)Executors.newFixedThreadPool(int nThreads,ThreadFactory threadFactory);//nThreads爲線程的數量,threadFactory建立線程的工廠方式
newSingleThreadExecutor
- 核心線程數與最大線程數均爲1
- 工做隊列是無界隊列
1public static ExecutorService newSingleThreadExecutor() { 2 return new FinalizableDelegatedExecutorService 3 (new ThreadPoolExecutor(1, 1, 4 0L, TimeUnit.MILLISECONDS, 5 new LinkedBlockingQueue<Runnable>())); 6 }
做用
建立一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程。(注意,若是由於在關閉前的執行期間出現失敗而終止了此單個線程,那麼若是須要,一個新線程將代替它執行後續的任務)。可保證順序地執行各個任務,而且在任意給定的時間不會有多個線程是活動的。與其餘等效的 newFixedThreadPool(1) 不一樣,可保證無需從新配置此方法所返回的執行程序便可使用其餘的線程。
特徵
線程池中最多執行1個線程,以後提交的線程活動將會排在隊列中以此執行。
建立方式
1(1)Executors.newSingleThreadExecutor() ; 2(2)Executors.newSingleThreadExecutor(ThreadFactory threadFactory);// threadFactory建立線程的工廠方式
newScheduledThreadPool
- 指定核心線程數corePoolSize
- 最大線程數是Integer.MAX_VALUE
- DelayedWorkQueue:任務隊列會根據任務延時時間的優先級進行執行
1public class ScheduledThreadPoolExecutor 2 extends ThreadPoolExecutor 3 implements ScheduledExecutorService { 4 .................... 5 /** 6 * Creates a new {@code ScheduledThreadPoolExecutor} with the 7 * given core pool size. 8 * 9 * @param corePoolSize the number of threads to keep in the pool, even 10 * if they are idle, unless {@code allowCoreThreadTimeOut} is set 11 * @throws IllegalArgumentException if {@code corePoolSize < 0} 12 */ 13 public ScheduledThreadPoolExecutor(int corePoolSize) { 14 super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, 15 new DelayedWorkQueue()); 16 } 17 ....................... 18}
做用
建立一個線程池,它可安排在給定延遲後運行命令或者按期地執行。
特徵
(1)線程池中具備指定數量的線程,即使是空線程也將保留
(2)可定時或者延遲執行線程活動
建立方式
1(1)Executors.newScheduledThreadPool(int corePoolSize);// corePoolSize線程的個數 2(2)newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);// corePoolSize線程的個數,threadFactory建立線程的工廠
newSingleThreadScheduledExecutor
做用
建立一個單線程執行程序,它可安排在給定延遲後運行命令或者按期地執行。
特徵
(1)線程池中最多執行1個線程,以後提交的線程活動將會排在隊列中以此執行
(2)可定時或者延遲執行線程活動
建立方式
1(1)Executors.newSingleThreadScheduledExecutor() ; 2(2)Executors.newSingleThreadScheduledExecutor(ThreadFactory threadFactory);//threadFactory建立線程的工廠
工做隊列
SynchronousQueue:直接提交
是工做隊列的默認選項,將任務直接提交給線程而不保持。
若是不存在可用於當即運行任務的線程,則試圖把任務加入隊列將失敗,所以會構造一個新的線程。
優缺點
優勢:能夠避免在處理可能具備內部依賴性的請求集時出現鎖。
直接提交一般要求無界maximumPoolSizes 以免拒絕新提交的任務。
當命令以超過隊列所能處理的平均數連續到達時,此策略容許無界線程具備增加的可能性。
ArrayBlockingQueue:無界隊列
在全部核心線程都忙時,新任務在隊列中等待。
所以,僅建立corePoolSize線程便可。(maximumPoolSize的值沒有任何做用。)
當每一個任務徹底獨立於其餘任務時,所以任務不會影響彼此的執行。
優缺點
優勢:例如,在網頁服務器中,儘管這種排隊方式對於消除短暫的突發請求頗有用。
缺點:當命令請求到達速度比其處理速度更快時,工做隊列無限制增加。
LinkedBlockingQueue:有界隊列
當與有限的maximumPoolSizes一塊兒使用時,有界隊列有助於防止資源耗盡,可是調整和控制起來會更加困難。
隊列大小和最大池大小能夠相互權衡
- 使用大隊列和小池能夠最大程度地減小CPU使用率,操做系統資源和上下文切換開銷,但可能致使人爲地下降吞吐量。
- 若是任務頻繁阻塞(例如若是它們是受I/O約束的),則系統可能能夠爲非預約的更多線程安排時間。
- 使用小隊列一般須要更大的池大小,這會使CPU繁忙,但可能會遇到不可接受的調度開銷,這也會下降吞吐量。
拒絕策略
AbortPolicy:處理程序遭到拒絕將拋出運行時 RejectedExecutionException
DiscardPolicy:不能執行的任務將被刪除
DiscardOldestPolicy:若是執行程序還沒有關閉,則位於工做隊列頭部的任務將被刪除,而後重試執行程序(若是再次失敗,則重複此過程)
CallerRunsPolicy:線程調用運行該任務的 execute 自己。此策略提供簡單的反饋控制機制,可以減緩新任務的提交速度。
1RejectedExecutionHandler rejected = null; 2 3rejected = new ThreadPoolExecutor.AbortPolicy();//默認,隊列滿了丟任務拋出異常 4 5rejected = new ThreadPoolExecutor.DiscardPolicy();//隊列滿了丟任務不異常 6 7rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//將最先進入隊列的任務刪,以後再嘗試加入隊列 8 9rejected = new ThreadPoolExecutor.CallerRunsPolicy();//若是添加到線程池失敗,那麼主線程會本身去執行該任務
總結
我們玩歸玩,鬧歸鬧,別拿面試開玩笑。
線程池記憶口訣:七個參數,四大特性,五個種類、三大工做隊列、四大拒絕策略
線程池,在面試中出現的次數很是多,你們面試前要把知識點記牢。