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

首頁 > 編程 > Java > 正文

Java 線程池ExecutorService詳解及實例代碼

2019-11-26 13:30:23
字體:
來源:轉載
供稿:網友

Java 線程池ExecutorService

1.線程池 

1.1什么情況下使用線程池

  1. 單個任務處理的時間比較短.
  2. 將需處理的任務的數量大.

1.2使用線程池的好處

  1. 減少在創建和銷毀線程上所花的時間以及系統資源的開銷.
  2. 如果不使用線程池,有可能造成系統創建大量線程而導致消耗系統內存以及”過度切換”;

2.ExecutorService和Executors

2.1簡介

ExecutorService是一個接口,繼承了Executor,

public interface ExecutorService extend Executor{}

Executor也是一個接口,該接口只包含一個方法:

public interface Executor {  void execute(Runnable command);}

Java里面的線程池的頂級接口是Excutor,但是嚴格意義上來說>>Exector并不是一個線程池,而只是一個執行線程的工具,真正的線程>池接口是ExecutorService.

3.Executors

它是一個靜態工廠類,它能生產不同類型的線程池,部分源碼如下:

public class Executors {//newFixedThreadPoolpublic static ExecutorService newFixedThreadPool(int nThreads) {    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}//newCacheThreadPool public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());  } //newScheduledThreadPool  public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {    return new ScheduledThreadPoolExecutor(corePoolSize);  }  //newStringooo}

先看一個具體的例子,用例子來說明它們之間的異同.

package thread;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;/** * Created by yang on 16-7-11. */public class Ch09_Executor {  private static void run(ExecutorService threadPool) {    for (int i = 1; i < 5; i++) {      final int taskID=i;      threadPool.execute(new Runnable() {        @Override        public void run() {          for(int i=1;i<5;i++){            try{              Thread.sleep(20);            }catch (InterruptedException e)            {              e.printStackTrace();            }            System.out.println("第"+taskID+"次任務的第"+i+"次執行");          }        }      });    }    threadPool.shutdown();  }  public static void main(String[] args) {    //創建可以容納3個線程的線程池    ExecutorService fixedThreadPool= Executors.newFixedThreadPool(3);    //線程池的大小會根據執行的任務動態的分配    ExecutorService cacheThreadPool=Executors.newCachedThreadPool();    //創建單個線程的線程池,如果當前線程在執行任務時突然中斷,則會創建一個新的線程替換它繼續執行.    ExecutorService singleThreadPool=Executors.newSingleThreadExecutor();    //效果類似于Timer定時器    ScheduledExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(3);    // run(fixedThreadPool); //(1)    //run(cacheThreadPool); //(2)    // run(singleThreadPool); //(3)    // run(scheduledThreadPool); //(4)  }}

4. 4種常用的線程池

4.1 CachedThreadPool

CachedThreadPool會創建一個緩存區,將初始化的線程緩存起來,會終止并且從緩存中移除已有6秒未被使用的線程.
如果線程有可用,就使用之前創建好的線程.如果線程沒有可用的,就新創建線程.

.重用:

緩存型池子,先看看池中有沒有以前建立的線程,如果有,就reuse,如果沒有,就新建一個新的線程加入池中,

使用場景:

緩存型池子通常用于執行一些生存期很短的異步型任務,因此在一些面向連接的Daemon型SERVER中用地不多.

超時:

能reuse的線程,必須是timeout IDLE內的池中線程,缺省timeout是60s,超過這個IDLE時長,線程實例將被終止及移除池.

結束:

放入CachedThreadPool的線程不必擔心其結束,超過TIMEOUT不活動,其會被自動終止.

實例解說:

去掉(2)的注釋,運行,得到的運行結果如下:

第1次任務的第1次執行第3次任務的第1次執行第2次任務的第1次執行第4次任務的第1次執行第3次任務的第2次執行第1次任務的第2次執行第2次任務的第2次執行第4次任務的第2次執行第3次任務的第3次執行第1次任務的第3次執行第2次任務的第3次執行第4次任務的第3次執行第3次任務的第4次執行第2次任務的第4次執行第4次任務的第4次執行第1次任務的第4次執行

從結果可以看出,4個任務是交替執行的.

4.2FixedThreadPool

在FixedThreadPool中,有一個固定大小的池,

如果當前需要執行的任務超過池大小,那么多出去的任務處于等待狀態,直到有空閑下來的線程執行任務。
如果當前需要執行的任務小于池大小,空閑線程不會被銷毀.

重用:

fixedThreadPool與cacheThreadPool差不多,也是能reuse就用,但不能隨時建新的線程

固定數目

其獨特之處在于,任意時間點,最多只能有固定數目的活動線程存在,此時如果有新的線程要建立,只能放在另外的隊列中等待,直到當前的線程中某個線程終止直接被移出池子

超時:

和cacheThreadPool不同,FixedThreadPool沒有IDLE機制

使用場景:

所以FixedThreadPool多數針對一些很穩定很固定的正規并發線程,多用于服務器

源碼分析:

從方法的源代碼看,cache池和fixed 池調用的是同一個底層池,只不過參數不同.
fixed池線程數固定,并且是0秒IDLE(無IDLE)
cache池線程數支持0-Integer.MAX_VALUE(顯然完全沒考慮主機的資源承受能力),60秒IDLE

實例解說:

去掉(1)的注釋,運行結果如下:

第1次任務的第1次執行第3次任務的第1次執行第2次任務的第1次執行第1次任務的第2次執行第3次任務的第2次執行第2次任務的第2次執行第1次任務的第3次執行第3次任務的第3次執行第2次任務的第3次執行第1次任務的第4次執行第3次任務的第4次執行第2次任務的第4次執行第4次任務的第1次執行第4次任務的第2次執行第4次任務的第3次執行第4次任務的第4次執行

創建了一個固定大小的線程池,容量是為3,然后循環執行4個任務,由輸出結果可以看出,前3個任務首先執行完,然后空閑下來的線程去執行第4個任務.

4.3SingleThreadExecutor

  1. SingleThreadExector得到的是一個單個線程,這個線程會保證你的任務執行完成.
  2. 單例線程,任意時間池中只能有一個線程
  3. 如果當前線程意外終止,會創建一個新的線程繼續執行任務,這和我們直接創建線程不同,也和newFixedThreadPool(1)不同.
  4. 用的是和cache池和fixed池相同的底層池,但線程數目是1-1,0秒IDLE(無IDLE)

去掉(3)注釋. 看執行結果如下:

第1次任務的第1次執行第1次任務的第2次執行第1次任務的第3次執行第1次任務的第4次執行第2次任務的第1次執行第2次任務的第2次執行第2次任務的第3次執行第2次任務的第4次執行第3次任務的第1次執行第3次任務的第2次執行第3次任務的第3次執行第3次任務的第4次執行第4次任務的第1次執行第4次任務的第2次執行第4次任務的第3次執行第4次任務的第4次執行

四個任務是順序執行的.

4.4 ScheduledThreadPool

ScheduledThreadPool是一個固定大小的線程池,與FixedThreadPool類似,執行的任務是定時任務.
去掉(4)的注釋得到的結果和FixedThreadPool得到的結果相同,ScheduledThreadPool的主要沒有在這里,而是定時任務,看下面這個例子:

package thread;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;/** * Created by yang on 16-7-11. */public class MyScheduledTask implements Runnable {  private String tname;  public MyScheduledTask(String name){    this.tname=name;  }  public void run(){    System.out.println(tname+"任務時延時2秒執行!");  }  public static void main(String[] args) {    ScheduledExecutorService scheduledPool= Executors.newScheduledThreadPool(2);    ScheduledExecutorService singSchedulePool=Executors.newSingleThreadScheduledExecutor();    MyScheduledTask mt1=new MyScheduledTask("mt1");    MyScheduledTask mt2=new MyScheduledTask("mt2");    //以scheduledThreadPool啟動mt1任務執行    scheduledPool.schedule(mt1,2, TimeUnit.SECONDS);    //用singlescheduledthreadPool啟動mt2;    singSchedulePool.schedule(mt2,2000,TimeUnit.MILLISECONDS);    scheduledPool.shutdown();    singSchedulePool.shutdown();  }}

結果:

mt1任務時延時2秒執行!mt2任務時延時2秒執行!

在程序運行2秒后,才會有結果顯示,說明線程在2秒后執行的.

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 科技| 景宁| 维西| 沂源县| 广丰县| 大埔区| 万全县| 遂昌县| 巴楚县| 陆河县| 鹿邑县| 吴江市| 大城县| 桃江县| 宁强县| 平果县| 阿城市| 武宣县| 青龙| 基隆市| 无极县| 鲁甸县| 克什克腾旗| 宁晋县| 青州市| 黎平县| 榆树市| 南昌市| 蓝山县| 丘北县| 阳新县| 达州市| 马尔康县| 双流县| 自贡市| 南靖县| 乌兰浩特市| 德安县| 志丹县| 大同县| 乌拉特前旗|