亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

最詳細的Java線程池原理解析

發布時間:2020-06-21 15:49:58 來源:網絡 閱讀:6302 作者:Java_老男孩 欄目:編程語言

一、為什么要用線程池

  1. 降低資源消耗。通過重復利用已創建的線程降低線程創建、銷毀線程造成的消耗。

  2. 提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。

  3. 提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配、調優和監控

二、ThreadPoolExecutor線程池類參數詳解

參數 說明
corePoolSize 核心線程數量,線程池維護線程的最少數量
maximumPoolSize 線程池維護線程的最大數量
keepAliveTime 線程池除核心線程外的其他線程的最長空閑時間,超過該時間的空閑線程會被銷毀
unit keepAliveTime的單位,TimeUnit中的幾個靜態屬性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS
workQueue 線程池所使用的任務緩沖隊列
threadFactory 線程工廠,用于創建線程,一般用默認的即可
handler 線程池對拒絕任務的處理策略

當線程池任務處理不過來的時候(什么時候認為處理不過來后面描述),可以通過handler指定的策略進行處理,ThreadPoolExecutor提供了四種策略:

  1. ThreadPoolExecutor.AbortPolicy:丟棄任務并拋出RejectedExecutionException異常;也是默認的處理方式。
  2. ThreadPoolExecutor.DiscardPolicy:丟棄任務,但是不拋出異常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)
  4. ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務

可以通過實現RejectedExecutionHandler接口自定義處理方式。

三、線程池任務執行

1. 添加執行任務

  • submit() 該方法返回一個Future對象,可執行帶返回值的線程;或者執行想隨時可以取消的線程。Future對象的get()方法獲取返回值。Future對象的cancel(true/false)取消任務,未開始或已完成返回false,參數表示是否中斷執行中的線程
  • execute() 沒有返回值。

2. 線程池任務提交過程

2.1. 如果此時線程池中的數量小于corePoolSize,即使線程池中的線程都處于空閑狀態,也要創建新的線程來處理被添加的任務。
2.2. 如果此時線程池中的數量等于corePoolSize,但是緩沖隊列workQueue未滿,那么任務被放入緩沖隊列。
2.3. 如果此時線程池中的數量大于等于corePoolSize,緩沖隊列workQueue滿,并且線程池中的數量小于maximumPoolSize,建新的線程來處理被添加的任務。
2.4. 如果此時線程池中的數量大于corePoolSize,緩沖隊列workQueue滿,并且線程池中的數量等于maximumPoolSize,那么通過 handler所指定的策略來處理此任務。
2.5. 當線程池中的線程數量大于 corePoolSize時,如果某線程空閑時間超過keepAliveTime,線程將被終止。這樣,線程池可以動態的調整池中的線程數。

總結即:處理任務判斷的優先級為 核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。

注意:

  1. 當workQueue使用的是×××限隊列時,maximumPoolSize參數就變的無意義了,比如new LinkedBlockingQueue(),或者new ArrayBlockingQueue(Integer.MAX_VALUE);
  2. 使用SynchronousQueue隊列時由于該隊列沒有容量的特性,所以不會對任務進行排隊,如果線程池中沒有空閑線程,會立即創建一個新線程來接收這個任務。maximumPoolSize要設置大一點。
  3. 核心線程和最大線程數量相等時keepAliveTime無作用.

3. 線程池關閉

3.1. shutdown() 不接收新任務,會處理已添加任務
3.2. shutdownNow() 不接受新任務,不處理已添加任務,中斷正在處理的任務

4. 常用隊列介紹

4.1. ArrayBlockingQueue: 這是一個由數組實現的容量固定的有界阻塞隊列.
4.2. SynchronousQueue: 沒有容量,不能緩存數據;每個put必須等待一個take; offer()的時候如果沒有另一個線程在poll()或者take()的話返回false。
4.3. LinkedBlockingQueue: 這是一個由單鏈表實現的默認×××的阻塞隊列。LinkedBlockingQueue提供了一個可選有界的構造函數,而在未指明容量時,容量默認為Integer.MAX_VALUE。

隊列操作:

方法 說明
add 增加一個元索; 如果隊列已滿,則拋出一個異常
remove 移除并返回隊列頭部的元素; 如果隊列為空,則拋出一個異常
offer 添加一個元素并返回true; 如果隊列已滿,則返回false
poll 移除并返回隊列頭部的元素; 如果隊列為空,則返回null
put 添加一個元素; 如果隊列滿,則阻塞
take 移除并返回隊列頭部的元素; 如果隊列為空,則阻塞
element 返回隊列頭部的元素; 如果隊列為空,則拋出一個異常
peek 返回隊列頭部的元素; 如果隊列為空,則返回null

5. Executors線程工廠類

1. Executors.newCachedThreadPool();
說明: 創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程.
內部實現:new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<runnable>());</runnable>

2. Executors.newFixedThreadPool(int);
說明: 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
內部實現:new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>());</runnable>

3. Executors.newSingleThreadExecutor();
說明:創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照順序執行。
內部實現:new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>())</runnable>

4. Executors.newScheduledThreadPool(int);
說明:創建一個定長線程池,支持定時及周期性任務執行。
內部實現:new ScheduledThreadPoolExecutor(corePoolSize)

【附】阿里巴巴Java開發手冊中對線程池的使用規范

  1. 【強制】創建線程或線程池時請指定有意義的線程名稱,方便出錯時回溯。
    正例:

    public class TimerTaskThread extends Thread {
    public TimerTaskThread(){
        super.setName("TimerTaskThread"); 
        ...
    }
    }
  2. 【強制】線程資源必須通過線程池提供,不允許在應用中自行顯式創建線程。
    說明: 使用線程池的好處是減少在創建和銷毀線程上所花的時間以及系統資源的開銷,解決資
    源不足的問題。如果不使用線程池,有可能造成系統創建大量同類線程而導致消耗完內存或者
    “過度切換”的問題。

  3. 【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣
    的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。

說明: Executors 返回的線程池對象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:
允許的請求隊列長度為 Integer.MAX_VALUE,可能會堆積大量的請求,從而導致 OOM。
2) CachedThreadPool 和 ScheduledThreadPool:
允許的創建線程數量為 Integer.MAX_VALUE, 可能會創建大量的線程,從而導致 OOM。

6. 總結

ThreadPoolExecutor通過幾個核心參數來定義不同類型的線程池,適用于不同的使用場景;其中在任務提交時,會依次判斷corePoolSize, workQueque, 及maximumPoolSize,不同的狀態不同的處理。技術領域水太深,如果不是日常使用,基本一段時間后某些知識點就忘的差不多了,因此階段性地回顧與總結,對夯實自己的技術基礎很有必要。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

潞西市| 台安县| 来安县| 红原县| 隆子县| 金堂县| 连城县| 平谷区| 博白县| 丽水市| 扎兰屯市| 梁河县| 保德县| 澄江县| 蒙城县| 龙里县| 竹北市| 辉县市| 赫章县| 兰州市| 九台市| 池州市| 翁源县| 潮安县| 嵩明县| 越西县| 项城市| 衢州市| 扬州市| 高清| 金秀| 西华县| 河东区| 旬邑县| 浮梁县| 棋牌| 衡阳县| 苏尼特左旗| 德兴市| 屏边| 东阿县|