国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > Java > 正文

線程池ThreadPoolExecutor使用簡介與方法實(shí)例

2024-07-14 08:43:47
字體:
供稿:網(wǎng)友

一、簡介

線程池類為 java.util.concurrent.ThreadPoolExecutor,常用構(gòu)造方法為:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) 
  • corePoolSize: 線程池維護(hù)線程的最少數(shù)量
  • maximumPoolSize:線程池維護(hù)線程的最大數(shù)量
  • keepAliveTime: 線程池維護(hù)線程所允許的空閑時(shí)間
  • unit: 線程池維護(hù)線程所允許的空閑時(shí)間的單位
  • workQueue: 線程池所使用的緩沖隊(duì)列
  • handler: 線程池對(duì)拒絕任務(wù)的處理策略

一個(gè)任務(wù)通過 execute(Runnable)方法被添加到線程池,任務(wù)就是一個(gè) Runnable類型的對(duì)象,任務(wù)的執(zhí)行方法就是 Runnable類型對(duì)象的run()方法。

當(dāng)一個(gè)任務(wù)通過execute(Runnable)方法欲添加到線程池時(shí):

  • 如果此時(shí)線程池中的數(shù)量小于corePoolSize,即使線程池中的線程都處于空閑狀態(tài),也要?jiǎng)?chuàng)建新的線程來處理被添加的任務(wù)。
  • 如果此時(shí)線程池中的數(shù)量等于 corePoolSize,但是緩沖隊(duì)列 workQueue未滿,那么任務(wù)被放入緩沖隊(duì)列。
  • 如果此時(shí)線程池中的數(shù)量大于corePoolSize,緩沖隊(duì)列workQueue滿,并且線程池中的數(shù)量小于maximumPoolSize,建新的線程來處理被添加的任務(wù)。
  • 如果此時(shí)線程池中的數(shù)量大于corePoolSize,緩沖隊(duì)列workQueue滿,并且線程池中的數(shù)量等于maximumPoolSize,那么通過 handler所指定的策略來處理此任務(wù)。

也就是:處理任務(wù)的優(yōu)先級(jí)為:

核心線程corePoolSize、任務(wù)隊(duì)列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務(wù)。

當(dāng)線程池中的線程數(shù)量大于 corePoolSize時(shí),如果某線程空閑時(shí)間超過keepAliveTime,線程將被終止。這樣,線程池可以動(dòng)態(tài)的調(diào)整池中的線程數(shù)。

unit可選的參數(shù)為java.util.concurrent.TimeUnit中的幾個(gè)靜態(tài)屬性:

NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。

workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue

handler有四個(gè)選擇:

  • ThreadPoolExecutor.AbortPolicy() 拋出java.util.concurrent.RejectedExecutionException異常
  • ThreadPoolExecutor.CallerRunsPolicy() 重試添加當(dāng)前的任務(wù),他會(huì)自動(dòng)重復(fù)調(diào)用execute()方法
  • ThreadPoolExecutor.DiscardOldestPolicy() 拋棄舊的任務(wù)
  • ThreadPoolExecutor.DiscardPolicy() 拋棄當(dāng)前的任務(wù)

二、一般用法舉例

package demo;import java.io.Serializable;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class TestThreadPool2{  private static int produceTaskSleepTime = 2;  private static int produceTaskMaxNumber = 10;  public static void main(String[] args)  {    // 構(gòu)造一個(gè)線程池    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),        new ThreadPoolExecutor.DiscardOldestPolicy());    for (int i = 1; i <= produceTaskMaxNumber; i++)    {      try      {        // 產(chǎn)生一個(gè)任務(wù),并將其加入到線程池        String task = "task@ " + i;        System.out.println("put " + task);        threadPool.execute(new ThreadPoolTask(task));        // 便于觀察,等待一段時(shí)間        Thread.sleep(produceTaskSleepTime);      }      catch (Exception e)      {        e.printStackTrace();      }    }  }}/** * 線程池執(zhí)行的任務(wù) */class ThreadPoolTask implements Runnable, Serializable{  private static final long serialVersionUID = 0;  private static int consumeTaskSleepTime = 2000;  // 保存任務(wù)所需要的數(shù)據(jù)  private Object threadPoolTaskData;  ThreadPoolTask(Object tasks)  {    this.threadPoolTaskData = tasks;  }  public void run()  {    // 處理一個(gè)任務(wù),這里的處理方式太簡單了,僅僅是一個(gè)打印語句    System.out.println(Thread.currentThread().getName());    System.out.println("start .." + threadPoolTaskData);    try    {      // //便于觀察,等待一段時(shí)間      Thread.sleep(consumeTaskSleepTime);    }    catch (Exception e)    {      e.printStackTrace();    }    threadPoolTaskData = null;  }  public Object getTask()  {    return this.threadPoolTaskData;  }}

說明:

1、在這段程序中,一個(gè)任務(wù)就是一個(gè)Runnable類型的對(duì)象,也就是一個(gè)ThreadPoolTask類型的對(duì)象。

2、一般來說任務(wù)除了處理方式外,還需要處理的數(shù)據(jù),處理的數(shù)據(jù)通過構(gòu)造方法傳給任務(wù)。

3、在這段程序中,main()方法相當(dāng)于一個(gè)殘忍的領(lǐng)導(dǎo),他派發(fā)出許多任務(wù),丟給一個(gè)叫 threadPool的任勞任怨的小組來做。

這個(gè)小組里面隊(duì)員至少有兩個(gè),如果他們兩個(gè)忙不過來,任務(wù)就被放到任務(wù)列表里面。

如果積壓的任務(wù)過多,多到任務(wù)列表都裝不下(超過3個(gè))的時(shí)候,就雇傭新的隊(duì)員來幫忙。但是基于成本的考慮,不能雇傭太多的隊(duì)員,至多只能雇傭 4個(gè)。

如果四個(gè)隊(duì)員都在忙時(shí),再有新的任務(wù),這個(gè)小組就處理不了了,任務(wù)就會(huì)被通過一種策略來處理,我們的處理方式是不停的派發(fā),直到接受這個(gè)任務(wù)為止(更殘忍!呵呵)。

因?yàn)殛?duì)員工作是需要成本的,如果工作很閑,閑到 3SECONDS都沒有新的任務(wù)了,那么有的隊(duì)員就會(huì)被解雇了,但是,為了小組的正常運(yùn)轉(zhuǎn),即使工作再閑,小組的隊(duì)員也不能少于兩個(gè)。

4、通過調(diào)整 produceTaskSleepTime和 consumeTaskSleepTime的大小來實(shí)現(xiàn)對(duì)派發(fā)任務(wù)和處理任務(wù)的速度的控制,改變這兩個(gè)值就可以觀察不同速率下程序的工作情況。

5、通過調(diào)整4中所指的數(shù)據(jù),再加上調(diào)整任務(wù)丟棄策略,換上其他三種策略,就可以看出不同策略下的不同處理方式。

6、對(duì)于其他的使用方法,參看jdk的幫助,很容易理解和使用。

另一個(gè)例子:

package demo;import java.util.Queue;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadPoolExecutorTest{  private static int queueDeep = 4;  public void createThreadPool()  {    /*      * 創(chuàng)建線程池,最小線程數(shù)為2,最大線程數(shù)為4,線程池維護(hù)線程的空閑時(shí)間為3秒,      * 使用隊(duì)列深度為4的有界隊(duì)列,如果執(zhí)行程序尚未關(guān)閉,則位于工作隊(duì)列頭部的任務(wù)將被刪除,      * 然后重試執(zhí)行程序(如果再次失敗,則重復(fù)此過程),里面已經(jīng)根據(jù)隊(duì)列深度對(duì)任務(wù)加載進(jìn)行了控制。      */     ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueDeep),        new ThreadPoolExecutor.DiscardOldestPolicy());    // 向線程池中添加 10 個(gè)任務(wù)    for (int i = 0; i < 10; i++)    {      try      {        Thread.sleep(1);      }      catch (InterruptedException e)      {        e.printStackTrace();      }      while (getQueueSize(tpe.getQueue()) >= queueDeep)      {        System.out.println("隊(duì)列已滿,等3秒再添加任務(wù)");        try        {          Thread.sleep(3000);        }        catch (InterruptedException e)        {          e.printStackTrace();        }      }      TaskThreadPool ttp = new TaskThreadPool(i);      System.out.println("put i:" + i);      tpe.execute(ttp);    }    tpe.shutdown();  }  private synchronized int getQueueSize(Queue queue)  {    return queue.size();  }  public static void main(String[] args)  {    ThreadPoolExecutorTest test = new ThreadPoolExecutorTest();    test.createThreadPool();  }  class TaskThreadPool implements Runnable  {    private int index;    public TaskThreadPool(int index)    {      this.index = index;    }    public void run()    {      System.out.println(Thread.currentThread() + " index:" + index);      try      {        Thread.sleep(3000);      }      catch (InterruptedException e)      {        e.printStackTrace();      }    }  }}

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JAVA教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 卢氏县| 阿巴嘎旗| 昌都县| 阜新市| 龙岩市| 新平| 涡阳县| 玉田县| 新绛县| 云浮市| 平乡县| 北川| 富宁县| 凉城县| 商都县| 卢湾区| 正阳县| 甘洛县| 三台县| 临汾市| 新营市| 陆丰市| 林甸县| 吴川市| 江门市| 德保县| 云龙县| 财经| 垫江县| 哈密市| 保山市| 拉萨市| 丰城市| 乌拉特后旗| 化州市| 宜兰县| 芦溪县| 延津县| 南部县| 剑阁县| 十堰市|