如何使用executors創(chuàng)建線程池?1.使用newfixedthreadpool(int nthreads)創(chuàng)建固定大小的線程池;2.使用newcachedthreadpool()創(chuàng)建可緩存線程池;3.使用newsinglethreadexecutor()創(chuàng)建單線程線程池;4.使用newscheduledthreadpool(int corepoolsize)創(chuàng)建支持定時和周期任務(wù)的線程池。線程池的拒絕策略是什么?如何自定義拒絕策略?默認使用abortpolicy,其他內(nèi)置策略包括callerrunspolicy、discardpolicy和discardoldestpolicy,自定義需實現(xiàn)rejectedexecutionhandler接口并在創(chuàng)建線程池時傳入。如何優(yōu)雅地關(guān)閉線程池?調(diào)用shutdown()平滑關(guān)閉,調(diào)用shutdownnow()立即停止任務(wù),結(jié)合awaittermination()等待任務(wù)完成或超時處理。如何監(jiān)控線程池的狀態(tài)?通過getpoolsize()、getactivecount()、getcompletedtaskcount()、gettaskcount()和getqueue().size()獲取狀態(tài)信息。executors創(chuàng)建的線程池有什么缺點?其隊列容量過大可能導(dǎo)致oom,newcachedthreadpool可能創(chuàng)建過多線程耗盡資源,推薦手動使用threadpoolexecutor創(chuàng)建以精確控制參數(shù)并避免風(fēng)險。
Executors類是Java并發(fā)包中一個強大的工具類,它簡化了線程池的創(chuàng)建和管理,提供了一系列靜態(tài)工廠方法,幫助開發(fā)者快速構(gòu)建各種類型的線程池,而無需深入了解線程池的底層細節(jié)。
Executors類主要用于創(chuàng)建不同類型的線程池,它隱藏了線程池的復(fù)雜性,使開發(fā)者能夠更專注于任務(wù)的執(zhí)行。
Executors類提供了多種靜態(tài)工廠方法,用于創(chuàng)建不同類型的線程池,以下是一些常用的方法:
立即學(xué)習(xí)“Java免費學(xué)習(xí)筆記(深入)”;
newFixedThreadPool(int nThreads): 創(chuàng)建一個固定大小的線程池,池中始終保持指定數(shù)量的線程。如果所有線程都在忙碌,新的任務(wù)將被放入隊列中等待。
ExecutorService executor = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) { executor.execute(new Task(i)); } executor.shutdown();
newCachedThreadPool(): 創(chuàng)建一個可緩存的線程池。如果線程池的大小超過了處理任務(wù)所需的數(shù)量,會自動回收空閑線程。當(dāng)有新任務(wù)提交時,如果沒有空閑線程可用,則會創(chuàng)建新的線程。這種線程池非常適合處理大量的短期異步任務(wù)。
ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 100; i++) { executor.execute(new Task(i)); } executor.shutdown();
newSingleThreadExecutor(): 創(chuàng)建一個單線程的線程池。所有提交的任務(wù)都會按照先進先出的順序執(zhí)行。如果線程在執(zhí)行任務(wù)時發(fā)生異常,會創(chuàng)建一個新的線程來替代它,保證所有任務(wù)都會被執(zhí)行。
ExecutorService executor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 100; i++) { executor.execute(new Task(i)); } executor.shutdown();
newScheduledThreadPool(int corePoolSize): 創(chuàng)建一個可以執(zhí)行定時任務(wù)和周期性任務(wù)的線程池。
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); executor.scheduleAtFixedRate(new Task(1), 1, 3, TimeUnit.SECONDS); // 每隔3秒執(zhí)行一次,延遲1秒后開始執(zhí)行
當(dāng)線程池的任務(wù)隊列已滿,且線程池中的所有線程都在忙碌時,如果再有新的任務(wù)提交,線程池會使用拒絕策略來處理這些任務(wù)。Executors創(chuàng)建的線程池默認使用ThreadPoolExecutor.AbortPolicy,該策略會直接拋出RejectedExecutionException異常。
Java提供了四種內(nèi)置的拒絕策略:
當(dāng)然,你也可以自定義拒絕策略,只需要實現(xiàn)RejectedExecutionHandler接口即可:
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; public class CustomRejectedExecutionHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println("Task " + r.toString() + " rejected from " + executor.toString()); // 可以添加自定義的拒絕處理邏輯,例如記錄日志、持久化任務(wù)等 } }
然后,在創(chuàng)建線程池時,將自定義的拒絕策略傳遞給ThreadPoolExecutor的構(gòu)造函數(shù):
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args) { int corePoolSize = 5; int maxPoolSize = 10; long keepAliveTime = 5000; ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100), // 任務(wù)隊列 new CustomRejectedExecutionHandler() // 自定義拒絕策略 ); for (int i = 0; i < 200; i++) { executor.execute(new Task(i)); } executor.shutdown(); } }
關(guān)閉線程池是一個重要的步驟,它可以防止資源泄漏。Executors創(chuàng)建的線程池提供了兩種關(guān)閉方法:shutdown()和shutdownNow()。
shutdown(): 平滑關(guān)閉線程池。它會阻止新的任務(wù)提交,但會等待所有已提交的任務(wù)執(zhí)行完成。
shutdownNow(): 立即關(guān)閉線程池。它會嘗試停止所有正在執(zhí)行的任務(wù),并返回一個包含所有等待執(zhí)行的任務(wù)的列表。需要注意的是,shutdownNow()方法并不能保證所有任務(wù)都會被立即停止,因為某些任務(wù)可能正在執(zhí)行一些無法中斷的操作。
在調(diào)用shutdown()或shutdownNow()方法后,可以使用awaitTermination()方法來等待線程池中的所有任務(wù)執(zhí)行完成,或者等待指定的超時時間。
ExecutorService executor = Executors.newFixedThreadPool(10); // 提交任務(wù)... executor.shutdown(); // 阻止新的任務(wù)提交 try { if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { // 等待60秒 executor.shutdownNow(); // 如果超時,則嘗試立即停止所有任務(wù) } } catch (InterruptedException e) { executor.shutdownNow(); // 如果當(dāng)前線程被中斷,則嘗試立即停止所有任務(wù) }
監(jiān)控線程池的狀態(tài)對于診斷性能問題和優(yōu)化線程池配置非常重要。ThreadPoolExecutor類提供了一些方法來獲取線程池的狀態(tài)信息:
你可以使用這些方法來定期監(jiān)控線程池的狀態(tài),并根據(jù)需要調(diào)整線程池的配置。例如,如果getQueue().size()持續(xù)增長,說明任務(wù)提交的速度超過了線程池的處理能力,可能需要增加線程池的大小。
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10); // 提交任務(wù)... while (true) { System.out.println("Pool Size: " + executor.getPoolSize()); System.out.println("Active Count: " + executor.getActiveCount()); System.out.println("Completed Task Count: " + executor.getCompletedTaskCount()); System.out.println("Task Count: " + executor.getTaskCount()); System.out.println("Queue Size: " + executor.getQueue().size()); Thread.sleep(1000); // 每隔1秒打印一次狀態(tài)信息 }
雖然Executors類簡化了線程池的創(chuàng)建,但它也存在一些缺點:
newFixedThreadPool()和newSingleThreadExecutor(): 它們的任務(wù)隊列使用了LinkedBlockingQueue,該隊列的默認容量是Integer.MAX_VALUE。如果任務(wù)提交的速度超過了線程池的處理能力,會導(dǎo)致大量的任務(wù)堆積在隊列中,最終可能導(dǎo)致OOM(OutOfMemoryError)異常。
newCachedThreadPool(): 它可以創(chuàng)建無限數(shù)量的線程,如果任務(wù)提交的速度過快,可能會創(chuàng)建大量的線程,導(dǎo)致系統(tǒng)資源耗盡。
因此,阿里巴巴Java開發(fā)手冊中建議使用ThreadPoolExecutor手動創(chuàng)建線程池,而不是使用Executors類。手動創(chuàng)建線程池可以更精確地控制線程池的參數(shù),例如核心線程數(shù)、最大線程數(shù)、任務(wù)隊列的類型和容量、拒絕策略等,從而避免潛在的風(fēng)險。
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Main { public static void main(String[] args) { int corePoolSize = 5; int maxPoolSize = 10; long keepAliveTime = 5000; ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100) // 任務(wù)隊列,設(shè)置容量 ); for (int i = 0; i < 200; i++) { executor.execute(new Task(i)); } executor.shutdown(); } }
總之,Executors類是Java并發(fā)編程中一個非常有用的工具,但需要了解其潛在的風(fēng)險,并根據(jù)實際情況選擇合適的線程池創(chuàng)建方式。在大多數(shù)情況下,推薦使用ThreadPoolExecutor手動創(chuàng)建線程池,以便更好地控制線程池的參數(shù),并避免潛在的OOM風(fēng)險。
以上就是Java中Executors類的用途 掌握線程池工廠的創(chuàng)建方法的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進程會占用資源并降低性能。幸運的是,許多工具可以讓 Windows 保持平穩(wěn)運行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://m.miracleart.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號