<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
對於作業系統而言,建立一個執行緒的代價是十分昂貴的, 需要給它分配記憶體、列入排程,同時線上程切換時要執行記憶體換頁,清空 CPU 快取,切換回來時還要重新從記憶體中讀取資訊,破壞了資料的區域性性。因此在並行程式設計中,當執行緒建立過多時,會影響程式效能,甚至引起程式崩潰。
而執行緒池屬於池化管理模式,具有以下優點:
執行緒池包含 3 個核心部分:
當一個新任務提交至執行緒池之後,執行緒池的處理流程如下:
當 ThreadPoolExecutor 建立新執行緒時,通過 CAS 來更新執行緒池的狀態 ctl。
執行緒池的使用主要分為以下三個步驟:
執行緒池的真正實現類是 ThreadPoolExecutor,其構造方法有如下 4 種:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
下面詳細來看建構函式需要傳入的重點引數:
corePoolSize
(必需)執行緒池中的核心執行緒數,當提交一個任務時,執行緒池建立一個新執行緒執行任務,直到當前執行緒數等於 corePoolSize, 即使有其他空閒執行緒能夠執行新來的任務, 也會繼續建立執行緒;如果當前執行緒數為 corePoolSize,繼續提交的任務被儲存到阻塞佇列中,等待被執行;如果執行了執行緒池的 **prestartAllCoreThreads()**方法,執行緒池會提前建立並啟動所有核心執行緒。workQueue
(必需)用來儲存等待被執行的任務的阻塞佇列。ArrayBlockingQueue
: 基於陣列結構的有界阻塞佇列,按 FIFO 排序任務;LinkedBlockingQueue
: 基於連結串列結構的阻塞佇列,按 FIFO 排序任務,吞吐量通常要高於 ArrayBlockingQueue;SynchronousQueue
: 一個不儲存元素的阻塞佇列,每個插入操作必須等到另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量通常要高於 LinkedBlockingQueue;PriorityBlockingQueue
: 具有優先順序的無界阻塞佇列;maximumPoolSize
(必需)執行緒池中能容納的最大執行緒數。如果當前阻塞佇列滿了,且繼續提交任務,則建立新的執行緒執行任務,前提是當前執行緒數小於 maximumPoolSize;當阻塞佇列是無界佇列, 則 maximumPoolSize 則不起作用, 因為無法提交至核心執行緒池的執行緒會一直持續地放入 workQueue。keepAliveTime
(必需)執行緒閒置超時時長。如果超過該時長,非核心執行緒就會被回收。如果將 allowCoreThreadTimeout 設定為 true 時,核心執行緒也會超時回收。unit
(必需)keepAliveTime 的單位,常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)threadFactory
(可選)建立執行緒的工廠,通過自定義的執行緒工廠可以給每個新建的執行緒設定一個具有識別度的執行緒名。預設為 DefaultThreadFactoryhandler
(可選)執行緒池的飽和策略,當阻塞佇列滿了,且沒有空閒的工作執行緒,如果繼續提交任務,必須採取一種策略處理該任務,執行緒池提供了 4 種策略:AbortPolicy
: 直接丟擲異常,預設策略;CallerRunsPolicy
: 用呼叫者所在的執行緒來執行任務;DiscardOldestPolicy
: 丟棄阻塞佇列中靠最前的任務,並執行當前任務;DiscardPolicy
: 直接丟棄任務; 也可以根據應用場景實現 RejectedExecutionHandler 介面,自定義飽和策略,如記錄紀錄檔或持久化儲存不能處理的任務。除了呼叫 ThreadPoolExecutor 自定義執行緒池的方式,其實 Executors 也已經為我們封裝好了 4 種常見的功能執行緒池,如下:
定長執行緒池(FixedThreadPool)
// 1. 建立定長執行緒池物件 & 設定執行緒池執行緒數量固定為 3 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); // 2. 建立好 Runnable 類執行緒物件 & 需執行的任務 Runnable task = new Runnable(){ public void run() { ...//待執行的耗時任務 } }; // 3. 向執行緒池提交任務 fixedThreadPool.execute(task);
定時執行緒池(ScheduledThreadPool)
// 1. 建立定時執行緒池物件 & 設定執行緒池執行緒數量固定為 5 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); // 2. 建立好 Runnable 類執行緒物件 & 需執行的任務 Runnable task =new Runnable(){ public void run() { ...//待執行的耗時任務 } }; // 3. 向執行緒池提交任務 scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延遲 1s 後執行任務
可快取執行緒池(CachedThreadPool)
// 1. 建立可快取執行緒池物件 ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); // 2. 建立好 Runnable 類執行緒物件 & 需執行的任務 Runnable task =new Runnable(){ public void run() { ...//待執行的耗時任務 } }; // 3. 向執行緒池提交任務 cachedThreadPool.execute(task);
單執行緒化執行緒池(SingleThreadExecutor)
// 1. 建立單執行緒化執行緒池 ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); // 2. 建立好 Runnable 類執行緒物件 & 需執行的任務 Runnable task =new Runnable(){ public void run() { ...//待執行的耗時任務 } }; // 3. 向執行緒池提交任務 singleThreadExecutor.execute(task);
目前已不推薦使用功能執行緒池,而是通過自定義 ThreadPoolExecutor 的方式。因為直接使用功能執行緒池具有資源耗盡的風險。
向執行緒池提交任務的流程非常簡單,只需要向執行緒池的 execute 方法傳入 Runnable 物件即可。
// 向執行緒池提交任務 threadPool.execute(new Runnable() { @Override public void run() { ... //待執行的任務 } });
當執行緒池不再使用時,需要手動關閉以釋放資源。執行緒池關閉的原理是:遍歷執行緒池中的所有執行緒,然後逐個呼叫執行緒的 interrupt 方法來中斷執行緒。一般通過呼叫以下兩個方法:
使用 ThreadPoolExecutor 自定義執行緒池時,需要從任務的優先順序,任務的執行時間長短,任務的性質(CPU 密集/ IO 密集),任務的依賴關係這四個角度來分析。並且近可能地使用有界的工作佇列。
性質不同的任務可用使用不同規模的執行緒池分開處理:
到此這篇關於Java執行緒池 ThreadPoolExecutor 詳解的文章就介紹到這了,更多相關JavaThreadPoolExecutor內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45