最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2021年01月26日 09:04:06   作者:字母哥博客  
這篇文章主要介紹了Java 線程池的作用以及該如何使用,幫助大家更好的理解和學(xué)習(xí)Java的相關(guān)知識,感興趣的朋友可以了解下

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

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

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

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

上圖表示線程池初始化具有3 個線程,任務(wù)隊(duì)列中有5 個待運(yùn)行的任務(wù)對象。

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

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

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

二、線程池示例

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

創(chuàng)建線程池處理任務(wù)要遵循的步驟

  1. 創(chuàng)建一個任務(wù)對象(實(shí)現(xiàn)Runnable接口),用于執(zhí)行具體的任務(wù)邏輯
  2. 使用Executors創(chuàng)建線程池ExecutorService
  3. 將待執(zhí)行的任務(wù)對象交給ExecutorService進(jìn)行任務(wù)處理
  4. 停掉 Executor 線程池
//第一步: 創(chuàng)建一個任務(wù)對象(實(shí)現(xiàn)Runnable接口),用于執(zhí)行具體的任務(wù)邏輯 (Step 1) 
class Task implements Runnable {
  private String name;

  public Task(String s) {
    name = s;
  }

  // 打印任務(wù)名稱并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("任務(wù)初始化" + name +" = " + ft.format(d));
          //第一次執(zhí)行的時候,打印每一個任務(wù)的名稱及初始化的時間
        }
        else{
          Date d = new Date();
          SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
          System.out.println("任務(wù)正在執(zhí)行" + name +" = " + ft.format(d));
          // 打印每一個任務(wù)處理的執(zhí)行時間
        }
        Thread.sleep(1000);
      }
      System.out.println("任務(wù)執(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個任務(wù)
    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í)行的任務(wù)對象交給ExecutorService進(jìn)行任務(wù)處理
    pool.execute(r1);
    pool.execute(r2);
    pool.execute(r3);
    pool.execute(r4);
    pool.execute(r5);

    // 第四步:關(guān)閉線程池
    pool.shutdown();
  }
} 

示例執(zhí)行結(jié)果

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

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

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

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

三、使用線程池的注意事項(xiàng)與調(diào)優(yōu)

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

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

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

原文鏈接:字母哥博客。

以上就是Java 線程池的作用以及該如何使用的詳細(xì)內(nèi)容,更多關(guān)于Java 線程池的作用和使用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring實(shí)現(xiàn)類私有方法的幾個問題(親測通用解決方案)

    Spring實(shí)現(xiàn)類私有方法的幾個問題(親測通用解決方案)

    現(xiàn)實(shí)的業(yè)務(wù)場景中,可能需要對Spring的實(shí)現(xiàn)類的私有方法進(jìn)行測試。本文給大家分享Spring實(shí)現(xiàn)類私有方法面臨的幾個問題及解決方案,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • JDK1.7以上javaFTP上傳刪除文件的實(shí)現(xiàn)方法

    JDK1.7以上javaFTP上傳刪除文件的實(shí)現(xiàn)方法

    下面小編就為大家分享一篇JDK1.7以上javaFTP上傳刪除文件的實(shí)現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11
  • Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫的方法

    Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫的方法,結(jié)合實(shí)例形式分析了java使用JDBC實(shí)現(xiàn)針對mysql數(shù)據(jù)庫的連接、查詢、輸出等相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • Spring執(zhí)行sql腳本文件的方法

    Spring執(zhí)行sql腳本文件的方法

    這篇文章主要介紹了Spring執(zhí)行sql腳本文件的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Springboot Thymeleaf字符串對象實(shí)例解析

    Springboot Thymeleaf字符串對象實(shí)例解析

    這篇文章主要介紹了Springboot Thymeleaf字符串對象實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2007-09-09
  • SpringBoot與rabbitmq的結(jié)合的示例

    SpringBoot與rabbitmq的結(jié)合的示例

    這篇文章主要介紹了SpringBoot與rabbitmq的結(jié)合的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • eclipse 聯(lián)想功能設(shè)置技巧

    eclipse 聯(lián)想功能設(shè)置技巧

    本文主要介紹了eclipse 聯(lián)想功能設(shè)置技巧的相關(guān)內(nèi)容,還是比較不錯的,需要的朋友可以參考。
    2017-10-10
  • JavaWeb三大組件之一的Filter詳解

    JavaWeb三大組件之一的Filter詳解

    本篇文章主要介紹了JavaWeb三大組件之中的Filter過濾器詳解,實(shí)例分析了JavaWeb之Filter過濾器的使用技巧,非常具有實(shí)用價值,需要的朋友可以參考下
    2022-06-06
  • Java?Stream?API詳解與使用示例詳解

    Java?Stream?API詳解與使用示例詳解

    Java?Stream?API?是一個功能強(qiáng)大的工具,適用于處理集合和數(shù)據(jù)流,本文全面介紹了?Java?Stream?API?的概念、功能以及如何在?Java?中有效地使用它進(jìn)行集合和數(shù)據(jù)流的處理,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • 在Java內(nèi)存模型中測試并發(fā)程序代碼

    在Java內(nèi)存模型中測試并發(fā)程序代碼

    這篇文章主要介紹了在Java內(nèi)存模型中測試并發(fā)程序代碼,輔以文中所提到的JavaScript庫JCStress進(jìn)行,需要的朋友可以參考下
    2015-07-07

最新評論

金堂县| 抚顺市| 多伦县| 靖州| 定襄县| 法库县| 苗栗县| 尼玛县| 内江市| 武鸣县| 紫阳县| 普格县| 龙海市| 弋阳县| 肃北| 定安县| 沂南县| 健康| 云梦县| 仲巴县| 满洲里市| 年辖:市辖区| 苏尼特左旗| 射洪县| 林口县| 诸城市| 兴业县| 平度市| 儋州市| 敖汉旗| 九寨沟县| 禄丰县| 兴义市| 汤阴县| 来凤县| 南京市| 南开区| 嵩明县| 普洱| 镇平县| 五华县|