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

談?wù)凧ava 線程池

 更新時(shí)間:2020年08月25日 14:25:35   作者:aysaml  
這篇文章主要介紹了Java 線程池的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下

一、引言

池的概念大家并不陌生,數(shù)據(jù)庫連接池、線程池等...大體來說,有三個(gè)優(yōu)點(diǎn):

  1. 降低資源消耗。
  2. 提高響應(yīng)速度。
  3. 便于統(tǒng)一管理。

以上是 “池化” 技術(shù)的相同特點(diǎn),至于他們之間的不同點(diǎn)這里不講,兩者都是為了提高性能和效率,拋開實(shí)際做連連看找不同,沒有意義。

同樣,類比于線程池來說:

  • 降低資源消耗:

重復(fù)利用線程池中已經(jīng)創(chuàng)建的線程,相比之下省去了線程創(chuàng)建和銷毀的性能消耗。

  • 提高響應(yīng)速度:

當(dāng)有任務(wù)創(chuàng)建時(shí),不必等待線程創(chuàng)建,可以立即執(zhí)行。

  • 便于統(tǒng)一管理:

使用線程池,可以對(duì)線程統(tǒng)一管理,對(duì)線程的執(zhí)行狀態(tài)做統(tǒng)一監(jiān)控。

二、線程池的使用

public ThreadPoolExecutor(int corePoolSize,
             int maximumPoolSize,
             long keepAliveTime,
             TimeUnit unit,
             BlockingQueue<Runnable> workQueue,
       ThreadFactory threadFactory,
             RejectedExecutionHandler handler);

1、關(guān)鍵參數(shù)

  • corePoolSize 核心線程數(shù)

當(dāng)向線程池中提交一個(gè)任務(wù)時(shí),如果線程池中的線程數(shù)量小于核心線程數(shù),即使存在空閑線程,也會(huì)新建一個(gè)線程來執(zhí)行當(dāng)前任務(wù),直到線程數(shù)量大于或等于核心線程數(shù)。

  • maximunPoolSize 最大線程數(shù)

當(dāng)任務(wù)隊(duì)列滿了,線程池中的線程數(shù)量小于最大線程數(shù)時(shí),創(chuàng)建新線程執(zhí)行任務(wù)。對(duì)于無界隊(duì)列,忽略該參數(shù)。

  • keepAliveTime 線程存活時(shí)間

大于核心線程數(shù)的那一部分線程的存活時(shí)間,如果這部分線程空閑超過這段時(shí)間,則進(jìn)行銷毀。

  • workqueue 任務(wù)隊(duì)列

線程池中的線程數(shù)大于核心線程數(shù)時(shí),將任務(wù)放入此隊(duì)列等待執(zhí)行。

  • threadFactory 線程工廠

用于創(chuàng)建線程,工廠使用 new Threa() 的方式創(chuàng)建線程,并為每個(gè)線程做統(tǒng)一規(guī)則的命名:pool-m-thread-n(m為線程池的編號(hào),n為線程池內(nèi)的線程編號(hào))。

  • handler 飽和策略

當(dāng)線程池和隊(duì)列都滿了,則根據(jù)此策略處理任務(wù)。

2、任務(wù)隊(duì)列類型

名稱 描述
ArrayBlockingQueue 基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列,此隊(duì)列按 FIFO(先進(jìn)先出)原則對(duì)元素進(jìn)行排序。
LinkedBlockingQueue 基于鏈表結(jié)構(gòu)的阻塞隊(duì)列,此隊(duì)列按 FIFO (先進(jìn)先出) 排序元素,吞吐量通常要高于 ArrayBlockingQueue。Executors.newFixedThreadPool( ) 使用了這個(gè)隊(duì)列。
SynchronousQueue 不存儲(chǔ)元素的阻塞隊(duì)列。每個(gè)插入操作必須等到另一個(gè)線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于 LinkedBlockingQueue,靜態(tài)工廠方法 Executors.newCachedThreadPool( ) 使用了這個(gè)隊(duì)列。
PriorityBlockingQueue 具有優(yōu)先級(jí)的無限阻塞隊(duì)列。

3、飽和策略類型

策略名稱 特性
AbortPolicy 默認(rèn)的飽和策略,直接拋出 RejectedExecutionException 異常
DiscardPolicy 不處理,直接丟棄任務(wù)
CallerRunsPolicy 使用調(diào)用者的線程執(zhí)行任務(wù)
DiscardOldestPolicy 丟棄隊(duì)列里最近的一個(gè)任務(wù),執(zhí)行當(dāng)前任務(wù)

同時(shí),還可以自行實(shí)現(xiàn) RejectedExecutionHandler 接口來自定義飽和策略,比如記錄日志、持久化等等。

void execute(Runnable command)

ThreadFactory namedThreadFactory =
new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
ExecutorService executor =
new ThreadPoolExecutor(
10,  
1000,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10),
namedThreadFactory,
new ThreadPoolExecutor.AbortPolicy());
executor.execute(
() -> {
System.out.println(1111);
});

注意使用 execute 方法提交任務(wù)時(shí),沒有返回值。

Future<?> submit(Runnable task)

Future<Integer> future = executor.submit(() -> {
   return 1 + 1;
  });
Integer result = future.get();

還可以使用 submit 方法提交任務(wù),該方法返回一個(gè) Future 對(duì)象,通過 Future#get( ) 方法可以獲得任務(wù)的返回值,該方法會(huì)一直阻塞知道任務(wù)執(zhí)行完畢。還可以使用 Future#get(long timeout, TimeUnit unit) 方法,該方法會(huì)阻塞一段時(shí)間后立即返回,而這時(shí)任務(wù)可能沒有執(zhí)行完畢。

5、關(guān)閉線程池

ThreadPoolExecutor 提供了 shutdown( ) 和 shutdownNow( ) 兩個(gè)方法關(guān)閉線程池。原理是首先遍歷線程池的工作線程,依次調(diào)用 interrupt( ) 方法中斷線程,這樣看來如果無法響應(yīng)中斷的任務(wù)就不能終止。

兩者區(qū)別是:

shutdownNow( )
shutdown( )

如果調(diào)用了其中一種方法,isShutdown 方法就會(huì)返回 true。當(dāng)所有的任務(wù)都已關(guān)閉后, 才表示線程池關(guān)閉成功,這時(shí)調(diào)用 isTerminaed 方法會(huì)返回 true。實(shí)際應(yīng)用中可以根據(jù)任務(wù)是否 一定要執(zhí)行完畢 的特性,決定使用哪種方法關(guān)閉線程池。

6、合理的配置線程池

通常我們可以 根據(jù) CPU 核心數(shù)量來設(shè)計(jì)線程池?cái)?shù)量 。

可以通過 Runtime.getRuntime().availableProcessors() 方法獲得當(dāng)前設(shè)備的物理核心數(shù)量。值得注意的是,如果應(yīng)用運(yùn)行在一些 docker 或虛擬機(jī)容器上時(shí),該方法取得的是當(dāng)前物理機(jī)的 CPU 核心數(shù)。

  • IO 密集型 2nCPU
  • 計(jì)算密集型 nCPU+1

其中 n 為 CPU 核心數(shù)量。

為什么加 1:即使當(dāng)計(jì)算密集型的線程偶爾由于缺失故障或者其他原因而暫停時(shí),這個(gè)額外的線程也能確保 CPU 的時(shí)鐘周期不會(huì)被浪費(fèi)。

三、線程池的運(yùn)行過程

當(dāng)提交一個(gè)新任務(wù)時(shí),線程池的處理步驟:

  1. 判斷當(dāng)前線程池內(nèi)的線程數(shù)量是否小于核心線程數(shù),如果小于則新建線程執(zhí)行任務(wù)。否則,進(jìn)入下個(gè)階段。
  2. 判斷隊(duì)列是否已滿,如果沒滿,則將任務(wù)加入等待隊(duì)列。否則,進(jìn)入下個(gè)階段。
  3. 在上面基礎(chǔ)上判斷是否大于最大線程數(shù),如果是根據(jù)響應(yīng)的策略處理。否則,新建線程執(zhí)行當(dāng)前任務(wù)。

線程池的源碼比較簡單易懂,感興趣的小伙伴可以自行查看 java.util.concurrent.ThreadPoolExecutor ,在線程池中每個(gè)任務(wù)都被包裝為一個(gè)一個(gè)的 Worker ,下面簡單看下 Worker 的 run( ) 方法:

try {
      while (task != null || (task = getTask()) != null) {
        w.lock();
        // If pool is stopping, ensure thread is interrupted;
        // if not, ensure thread is not interrupted. This
        // requires a recheck in second case to deal with
        // shutdownNow race while clearing interrupt
        if ((runStateAtLeast(ctl.get(), STOP) ||
           (Thread.interrupted() &&
           runStateAtLeast(ctl.get(), STOP))) &&
          !wt.isInterrupted())
          wt.interrupt();
        try {
          beforeExecute(wt, task);
          Throwable thrown = null;
          try {
            task.run();
          } catch (RuntimeException x) {
            thrown = x; throw x;
          } catch (Error x) {
            thrown = x; throw x;
          } catch (Throwable x) {
            thrown = x; throw new Error(x);
          } finally {
            afterExecute(task, thrown);
          }
        } finally {
          task = null;
          w.completedTasks++;
          w.unlock();
        }
      }
      completedAbruptly = false;
    } finally {
      processWorkerExit(w, completedAbruptly);
    }

可以看到不斷的循環(huán)取出 Task 并執(zhí)行,而在任務(wù)的執(zhí)行前后,有 beforeExecute 和 afterExecute 方法,我們可以實(shí)現(xiàn)兩個(gè)方法實(shí)現(xiàn)一些監(jiān)控邏輯。除此之外還可以集合線程池的一些屬性或者重寫 terminated() 方法在線程池關(guān)閉時(shí)進(jìn)行監(jiān)控。

四、常見的幾種線程池實(shí)現(xiàn)

在 Executors 中提供了集中常見的線程池,分別應(yīng)用在不同的場景。

  • FixThreadPool 固定數(shù)量的線程池,適用于對(duì)線程管理,高負(fù)載的系統(tǒng)
  • SingleThreadPool 只有一個(gè)線程的線程池,適用于保證任務(wù)順序執(zhí)行
  • CacheThreadPool 創(chuàng)建一個(gè)不限制線程數(shù)量的線程池,適用于執(zhí)行短期異步任務(wù)的小程序,低負(fù)載系統(tǒng)
  • ScheduledThreadPool 定時(shí)任務(wù)使用的線程池,適用于定時(shí)任務(wù)

上面幾種線程池的特性主要依賴于 ThreadPoolExecutor 的幾個(gè)參數(shù)來實(shí)現(xiàn),不同的核心線程數(shù)量,以及不同類型的阻塞隊(duì)列,同時(shí)我們還可以自行實(shí)現(xiàn)自己的線程池滿足業(yè)務(wù)需求。

值得注意的是,并不推薦使用 Executors 創(chuàng)建線程池,詳見下:

Executors.newFixedThreadPool(int nThread)

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                   0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
 }

繼續(xù)來看 LinkedBlockingQueue :

public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
    if (capacity <= 0) throw new IllegalArgumentException();
    this.capacity = capacity;
    last = head = new Node<E>(null);
}

可以看到使用 LinkedBlockingQueue 創(chuàng)建的是 Integer.MAX_VALUE 大小的隊(duì)列,會(huì)堆積大量的請(qǐng)求,從而造成 OOM

Executors.newSingleThreadExexutor( )

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
      (new ThreadPoolExecutor(1, 1,
                  0L, TimeUnit.MILLISECONDS,
                  new LinkedBlockingQueue<Runnable>()));
}

同樣,使用的 LinkedBlockingQueue ,一樣的情況

Executors.newCachedThreadPool( )

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                   60L, TimeUnit.SECONDS,
                   new SynchronousQueue<Runnable>());
}

代碼課件線程池使用的最大線程數(shù)是 Integer.MAX_VALUE ,可能會(huì)創(chuàng)建大量線程,導(dǎo)致 OOM

Executors.newScheduleThreadPool()

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
       new DelayedWorkQueue());
}

和上面是一樣的問題,最大線程數(shù)是 Integer.MAX_VALUE
所以原則上來說禁止使用 Executors 創(chuàng)建線程池, 而使用 ThreadPoolExecutor 的構(gòu)造函數(shù)來創(chuàng)建線程池。

五、結(jié)語

線程池在開發(fā)中還是比較常見的,結(jié)合不同的業(yè)務(wù)場景,結(jié)合最佳實(shí)踐配置正確的參數(shù),可以幫助我們的應(yīng)用性能得到提升。

以上就是談?wù)凧ava 線程池的詳細(xì)內(nèi)容,更多關(guān)于Java 線程池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot集成JSR303參數(shù)校驗(yàn)的方法實(shí)現(xiàn)

    Springboot集成JSR303參數(shù)校驗(yàn)的方法實(shí)現(xiàn)

    這篇文章主要介紹了Springboot集成JSR303參數(shù)校驗(yàn)的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • java判斷http地址是否連通(示例代碼)

    java判斷http地址是否連通(示例代碼)

    這篇文章通過實(shí)例代碼給大家介紹了java判斷http地址是否連通,文末給大家補(bǔ)充知識(shí)點(diǎn)url.openconnection() 設(shè)置超時(shí)時(shí)間的方法,感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • SpringCloud 微服務(wù)最佳開發(fā)實(shí)踐

    SpringCloud 微服務(wù)最佳開發(fā)實(shí)踐

    本文結(jié)合我們實(shí)際的開發(fā)中遇到的一些問題整理出了一份微服務(wù)開發(fā)的實(shí)踐規(guī)范,對(duì)SpringCloud 微服務(wù)開發(fā)實(shí)踐相關(guān)知識(shí)感興趣的朋友一起看看吧
    2021-07-07
  • java數(shù)據(jù)結(jié)構(gòu)之java實(shí)現(xiàn)棧

    java數(shù)據(jù)結(jié)構(gòu)之java實(shí)現(xiàn)棧

    這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)棧,需要的朋友可以參考下
    2014-03-03
  • java實(shí)現(xiàn)識(shí)別二維碼圖片功能方法詳解與實(shí)例源碼

    java實(shí)現(xiàn)識(shí)別二維碼圖片功能方法詳解與實(shí)例源碼

    這篇文章主要介紹了java實(shí)現(xiàn)識(shí)別二維碼圖片,java無法識(shí)別二維碼情況下對(duì)二維碼圖片調(diào)優(yōu)功能方法與實(shí)例源碼,需要的朋友可以參考下
    2022-12-12
  • 基于JVM 中常見垃圾收集算法介紹

    基于JVM 中常見垃圾收集算法介紹

    下面小編就為大家分享一篇基于JVM 中常見垃圾收集算法介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • java堆排序原理及算法實(shí)現(xiàn)

    java堆排序原理及算法實(shí)現(xiàn)

    本篇文章主要介紹了堆排序的簡介,定義,算法實(shí)現(xiàn)以及堆排序的性質(zhì)。想要了解的朋友可以參考下
    2017-04-04
  • Spring深入分析容器接口作用

    Spring深入分析容器接口作用

    Spring內(nèi)部提供了很多表示Spring容器的接口和對(duì)象,我們今天來看看幾個(gè)比較常見的容器接口和具體的實(shí)現(xiàn)類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Spring Retry 重試實(shí)例詳解

    Spring Retry 重試實(shí)例詳解

    這篇文章主要介紹了Spring Retry 重試,使用方式有兩種分別是命令式和聲明式,本文通過實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2022-10-10
  • idea創(chuàng)建springboot項(xiàng)目,java版本只能選擇17和21的解決方案

    idea創(chuàng)建springboot項(xiàng)目,java版本只能選擇17和21的解決方案

    這篇文章主要介紹了idea創(chuàng)建springboot項(xiàng)目,java版本只能選擇17和21的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04

最新評(píng)論

温州市| 兴城市| 昆明市| 阿鲁科尔沁旗| 安义县| 灵台县| 安阳市| 乌兰县| 乐安县| 白玉县| 镇坪县| 金平| 双峰县| 阿拉尔市| 保亭| 柳江县| 云霄县| 瑞昌市| 明水县| 二连浩特市| 咸丰县| 加查县| 吉水县| 黄龙县| 西畴县| 厦门市| 垫江县| 阳泉市| 平远县| 宝山区| 崇信县| 平陆县| 三亚市| 留坝县| 枣强县| 霍邱县| 邵阳市| 垫江县| 衡南县| 车致| 安平县|