国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

Java 線程池的作用以及該如何使用

瀏覽:10日期:2022-08-17 15:56:26

服務端應用程序(如數(shù)據(jù)庫和 Web 服務器)需要處理來自客戶端的高并發(fā)、耗時較短的請求任務,所以頻繁的創(chuàng)建處理這些請求的所需要的線程就是一個非常消耗資源的操作。常規(guī)的方法是針對一個新的請求創(chuàng)建一個新線程,雖然這種方法似乎易于實現(xiàn),但它有重大缺點。為每個請求創(chuàng)建新線程將花費更多的時間,在創(chuàng)建和銷毀線程時花費更多的系統(tǒng)資源。因此同時創(chuàng)建太多線程的 JVM 可能會導致系統(tǒng)內(nèi)存不足,這就需要限制要創(chuàng)建的線程數(shù),也就是需要使用到線程池。

一、什么是 Java 中的線程池?

線程池技術就是線程的重用技術,使用之前創(chuàng)建好的線程來執(zhí)行當前任務,并提供了針對線程周期開銷和資源沖突問題的解決方案。 由于請求到達時線程已經(jīng)存在,因此消除了線程創(chuàng)建過程導致的延遲,使應用程序得到更快的響應。

Java提供了以Executor接口及其子接口ExecutorService和ThreadPoolExecutor為中心的執(zhí)行器框架。通過使用Executor,完成線程任務只需實現(xiàn) Runnable接口并將其交給執(zhí)行器執(zhí)行即可。 為您封裝好線程池,將您的編程任務側重于具體任務的實現(xiàn),而不是線程的實現(xiàn)機制。 若要使用線程池,我們首先創(chuàng)建一個 ExecutorService對象,然后向其傳遞一組任務。ThreadPoolExcutor 類則可以設置線程池初始化和最大的線程容量。

Java 線程池的作用以及該如何使用

上圖表示線程池初始化具有3 個線程,任務隊列中有5 個待運行的任務對象。

執(zhí)行器線程池方法

方法 描述 newFixedThreadPool(int) 創(chuàng)建具有固定的線程數(shù)的線程池,int參數(shù)表示線程池內(nèi)線程的數(shù)量 newCachedThreadPool() 創(chuàng)建一個可緩存線程池,該線程池可靈活回收空閑線程。若無空閑線程,則新建線程處理任務。 newSingleThreadExecutor() 創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務 newScheduledThreadPool 創(chuàng)建一個定長線程池,支持定時及周期性任務執(zhí)行

在固定線程池的情況下,如果執(zhí)行器當前運行的所有線程,則掛起的任務將放在隊列中,并在線程變?yōu)榭臻e時執(zhí)行。

二、線程池示例

在下面的內(nèi)容中,我們將介紹線程池的executor執(zhí)行器。

創(chuàng)建線程池處理任務要遵循的步驟 創(chuàng)建一個任務對象(實現(xiàn)Runnable接口),用于執(zhí)行具體的任務邏輯 使用Executors創(chuàng)建線程池ExecutorService 將待執(zhí)行的任務對象交給ExecutorService進行任務處理 停掉 Executor 線程池

//第一步: 創(chuàng)建一個任務對象(實現(xiàn)Runnable接口),用于執(zhí)行具體的任務邏輯 (Step 1) class Task implements Runnable { private String name; public Task(String s) { name = s; } // 打印任務名稱并Sleep 1秒 // 整個處理流程執(zhí)行5次 public void run() { try{ for (int i = 0; i<=5; i++) {if (i==0) { Date d = new Date(); SimpleDateFormat ft = new SimpleDateFormat('hh:mm:ss'); System.out.println('任務初始化' + name +' = ' + ft.format(d)); //第一次執(zhí)行的時候,打印每一個任務的名稱及初始化的時間}else{ Date d = new Date(); SimpleDateFormat ft = new SimpleDateFormat('hh:mm:ss'); System.out.println('任務正在執(zhí)行' + name +' = ' + ft.format(d)); // 打印每一個任務處理的執(zhí)行時間}Thread.sleep(1000); } System.out.println('任務執(zhí)行完成' + name); } catch(InterruptedException e) { e.printStackTrace(); } }}

測試用例

public class ThreadPoolTest { // 線程池里面最大線程數(shù)量 static final int MAX_SIZE = 3; public static void main (String[] args) { // 創(chuàng)建5個任務 Runnable r1 = new Task('task 1'); Runnable r2 = new Task('task 2'); Runnable r3 = new Task('task 3'); Runnable r4 = new Task('task 4'); Runnable r5 = new Task('task 5'); // 第二步:創(chuàng)建一個固定線程數(shù)量的線程池,線程數(shù)為MAX_SIZE ExecutorService pool = Executors.newFixedThreadPool(MAX_SIZE); // 第三步:將待執(zhí)行的任務對象交給ExecutorService進行任務處理 pool.execute(r1); pool.execute(r2); pool.execute(r3); pool.execute(r4); pool.execute(r5); // 第四步:關閉線程池 pool.shutdown(); }} 示例執(zhí)行結果

任務初始化task 1 = 05:25:55任務初始化task 2 = 05:25:55任務初始化task 3 = 05:25:55任務正在執(zhí)行task 3 = 05:25:56任務正在執(zhí)行task 1 = 05:25:56任務正在執(zhí)行task 2 = 05:25:56任務正在執(zhí)行task 1 = 05:25:57任務正在執(zhí)行task 3 = 05:25:57任務正在執(zhí)行task 2 = 05:25:57任務正在執(zhí)行task 3 = 05:25:58任務正在執(zhí)行task 1 = 05:25:58任務正在執(zhí)行task 2 = 05:25:58任務正在執(zhí)行task 2 = 05:25:59任務正在執(zhí)行task 3 = 05:25:59任務正在執(zhí)行task 1 = 05:25:59任務正在執(zhí)行task 1 = 05:26:00任務正在執(zhí)行task 2 = 05:26:00任務正在執(zhí)行task 3 = 05:26:00任務執(zhí)行完成task 3任務執(zhí)行完成task 2任務執(zhí)行完成task 1任務初始化task 5 = 05:26:01任務初始化task 4 = 05:26:01任務正在執(zhí)行task 4 = 05:26:02任務正在執(zhí)行task 5 = 05:26:02任務正在執(zhí)行task 4 = 05:26:03任務正在執(zhí)行task 5 = 05:26:03任務正在執(zhí)行task 5 = 05:26:04任務正在執(zhí)行task 4 = 05:26:04任務正在執(zhí)行task 4 = 05:26:05任務正在執(zhí)行task 5 = 05:26:05任務正在執(zhí)行task 4 = 05:26:06任務正在執(zhí)行task 5 = 05:26:06任務執(zhí)行完成task 4任務執(zhí)行完成task 5

如程序執(zhí)行結果中顯示的一樣,任務 4 或任務 5 僅在池中的線程變?yōu)榭臻e時才執(zhí)行。在此之前,額外的任務將放在待執(zhí)行的隊列中。

Java 線程池的作用以及該如何使用

線程池執(zhí)行前三個任務,線程池內(nèi)線程回收空出來之后再去處理執(zhí)行任務 4 和 5

Java 線程池的作用以及該如何使用

使用這種線程池方法的一個主要優(yōu)點是,假如您希望一次處理10000個請求,但不希望創(chuàng)建10000個線程,從而避免造成系統(tǒng)資源的過量使用導致的宕機。您可以使用此方法創(chuàng)建一個包含500個線程的線程池,并且可以向該線程池提交500個請求。ThreadPool此時將創(chuàng)建最多500個線程,一次處理500個請求。在任何一個線程的進程完成之后,ThreadPool將在內(nèi)部將第501個請求分配給該線程,并將繼續(xù)對所有剩余的請求執(zhí)行相同的操作。在系統(tǒng)資源比較緊張的情況下,線程池是保證程序穩(wěn)定運行的一個有效的解決方案。

三、使用線程池的注意事項與調(diào)優(yōu) 死鎖: 雖然死鎖可能發(fā)生在任何多線程程序中,但線程池引入了另一個死鎖案例,其中所有執(zhí)行線程都在等待隊列中某個阻塞線程的執(zhí)行結果,導致線程無法繼續(xù)執(zhí)行。 線程泄漏 : 如果線程池中線程在任務完成時未正確返回,將發(fā)生線程泄漏問題。例如,某個線程引發(fā)異常并且池類沒有捕獲此異常,則線程將異常退出,從而線程池的大小將減小一個。如果這種情況重復多次,則線程池最終將變?yōu)榭眨瑳]有線程可用于執(zhí)行其他任務。 線程頻繁輪換: 如果線程池大小非常大,則線程之間進行上下文切換會浪費很多時間。所以在系統(tǒng)資源允許的情況下,也不是線程池越大越好。

線程池大小優(yōu)化: 線程池的最佳大小取決于可用的處理器數(shù)量和待處理任務的性質(zhì)。對于CPU密集型任務,假設系統(tǒng)有N個邏輯處理核心,N 或 N+1 的最大線程池數(shù)量大小將實現(xiàn)最大效率。對于 I/O密集型任務,需要考慮請求的等待時間(W)和服務處理時間(S)的比例,線程池最大大小為 N*(1+ W/S)會實現(xiàn)最高效率。

不要教條的使用上面的總結,需要根據(jù)自己的應用任務處理類型進行靈活的設置與調(diào)優(yōu),其中少不了測試實驗。

原文鏈接:字母哥博客。

以上就是Java 線程池的作用以及該如何使用的詳細內(nèi)容,更多關于Java 線程池的作用和使用的資料請關注好吧啦網(wǎng)其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 久草网在线观看 | 亚洲视频国产精品 | 女人张开腿让男人桶免费最新 | 黄色毛片免费看 | 成人在线一区二区三区 | 国产一区二区三区在线视频 | 亚洲国产成a人v在线观看 | 久久国产精品久久久久久 | 国产成人免费不卡在线观看 | 日本三级日产三级国产三级 | 高清一区二区在线观看 | 国产微拍精品福利视频 | 91热久久免费频精品黑人99 | 亚洲国产精选 | 亚洲人成在线播放网站 | 欧美黄色一级在线 | 久久99久久成人免费播放 | 久久视频国产 | 欧美日韩视频在线第一区 | 性欧美一级 | 刺激免费视频 | 免费观看a级毛片在线播放 免费观看a级网站 | 99视频网址 | 欧美一线不卡在线播放 | 亚洲日本免费 | 男人女人做性全程视视频 | 东京一区二区三区高清视频 | 亚洲欧美日韩中文字幕在线一区 | 精品久久久久久久久免费影院 | 美女视频黄a视频免费全过程 | 1717she国产精品免费视频 | 91麻精品国产91久久久久 | 成人免费在线视频网 | 67194成人在线观看 | 亚洲一区二区免费 | 国语精品视频在线观看不卡 | 中文字幕一级片 | 国产精品久久久久久久午夜片 | 成人免费视频网站 | 欧美性夜欢 | www.黄色片网站 |