中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring boot中怎么使用ExecutorService線程池

發布時間:2021-06-11 15:31:33 來源:億速云 閱讀:519 作者:Leah 欄目:編程語言

本篇文章為大家展示了spring boot中怎么使用ExecutorService線程池,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

1. 認識java線程池

1.1 在什么情況下使用線程池?

  • 1.單個任務處理的時間比較短

  • 2.需處理的任務的數量大

1.2 使用線程池的好處:

  • 1.減少在創建和銷毀線程上所花的時間以及系統資源的開銷

  • 2.如不使用線程池,有可能造成系統創建大量線程而導致消耗完系統內存

1.3 線程池包括以下四個基本組成部分:

  • 1、線程池管理器(ThreadPool):用于創建并管理線程池,包括 創建線程池,銷毀線程池,添加新任務;

  • 2、工作線程(PoolWorker):線程池中線程,在沒有任務時處于等待狀態,可以循環的執行任務;

  • 3、任務接口(Task):每個任務必須實現的接口,以供工作線程調度任務的執行,它主要規定了任務的入口,任務執行完后的收尾工作,任務的執行狀態等;

  • 4、任務隊列(taskQueue):用于存放沒有處理的任務。提供一種緩沖機制。

1.4 線程池的核心參數

ThreadPoolExecutor 有四個構造方法,前三個都是調用最后一個(最后一個參數最全)

 public ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               long keepAliveTime,
               TimeUnit unit,
               BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
       Executors.defaultThreadFactory(), defaultHandler);
  }
  public ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               long keepAliveTime,
               TimeUnit unit,
               BlockingQueue<Runnable> workQueue,
               ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
       threadFactory, defaultHandler);
  }
  public ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               long keepAliveTime,
               TimeUnit unit,
               BlockingQueue<Runnable> workQueue,
               RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
       Executors.defaultThreadFactory(), handler);
  }
  // 都調用它
  public ThreadPoolExecutor(// 核心線程數
  int corePoolSize, 
               // 最大線程數
               int maximumPoolSize, 
               // 閑置線程存活時間
               long keepAliveTime, 
               // 時間單位
               TimeUnit unit, 
               // 線程隊列
               BlockingQueue<Runnable> workQueue, 
               // 線程工廠 
               ThreadFactory threadFactory,        
               // 隊列已滿,而且當前線程數已經超過最大線程數時的異常處理策略       
               RejectedExecutionHandler handler  ) {
    if (corePoolSize < 0 ||
      maximumPoolSize <= 0 ||
      maximumPoolSize < corePoolSize ||
      keepAliveTime < 0)
      throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
      throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
  }

主要參數

corePoolSize:核心線程數

  • 核心線程會一直存活,即使沒有任務需要執行

  • 當線程數小于核心線程數時,即使有線程空閑,線程池也會優先創建新線程處理

  • 設置allowCoreThreadTimeout=true(默認false)時,核心線程會超時關閉

maxPoolSize:最大線程數

  • 當線程數>=corePoolSize,且任務隊列已滿時。線程池會創建新線程來處理任務

  • 當線程數=maxPoolSize,且任務隊列已滿時,線程池會拒絕處理任務而拋出異常

keepAliveTime:線程空閑時間

  • 當線程空閑時間達到keepAliveTime時,線程會退出,直到線程數量=corePoolSize

  • 如果allowCoreThreadTimeout=true,則會直到線程數量=0

workQueue:一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這里的阻塞隊列有以下幾種選擇:

  • ArrayBlockingQueue;

  • LinkedBlockingQueue;

  • SynchronousQueue;

關于阻塞隊列可以看這篇:java 阻塞隊列

threadFactory:線程工廠,主要用來創建線程;

rejectedExecutionHandler:任務拒絕處理器,兩種情況會拒絕處理任務:

  • 當線程數已經達到maxPoolSize,切隊列已滿,會拒絕新任務

  • 當線程池被調用shutdown()后,會等待線程池里的任務執行完畢,再shutdown。如果在調用shutdown()和線程池真正shutdown之間提交任務,會拒絕新任務

當拒絕處理任務時線程池會調用rejectedExecutionHandler來處理這個任務。如果沒有設置默認是AbortPolicy,會拋出異常。ThreadPoolExecutor類有幾個內部實現類來處理這類情況:

  • AbortPolicy 丟棄任務,拋運行時異常

  • CallerRunsPolicy 執行任務

  • DiscardPolicy 忽視,什么都不會發生

  • DiscardOldestPolicy 從隊列中踢出最先進入隊列(最后一個執行)的任務

  • 實現RejectedExecutionHandler接口,可自定義處理器

1.5 Java線程池 ExecutorService

  • Executors.newCachedThreadPool 創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。

  • Executors.newFixedThreadPool 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。

  • Executors.newScheduledThreadPool 創建一個定長線程池,支持定時及周期性任務執行。

  • Executors.newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

備注:Executors只是一個工廠類,它所有的方法返回的都是ThreadPoolExecutor、ScheduledThreadPoolExecutor這兩個類的實例。

1.6 ExecutorService有如下幾個執行方法

  • executorService.execute(Runnable);這個方法接收一個Runnable實例,并且異步的執行

  • executorService.submit(Runnable)

  • executorService.submit(Callable)

  • executorService.invokeAny(…)

  • executorService.invokeAll(…)

execute(Runnable)

這個方法接收一個Runnable實例,并且異步的執行

executorService.execute(new Runnable() {
public void run() {
  System.out.println("Asynchronous task");
}
});
executorService.shutdown();

submit(Runnable)

submit(Runnable)和execute(Runnable)區別是前者可以返回一個Future對象,通過返回的Future對象,我們可以檢查提交的任務是否執行完畢,請看下面執行的例子:

Future future = executorService.submit(new Runnable() {
public void run() {
  System.out.println("Asynchronous task");
}
});
future.get(); //returns null if the task has finished correctly.

submit(Callable)

submit(Callable)和submit(Runnable)類似,也會返回一個Future對象,但是除此之外,submit(Callable)接收的是一個Callable的實現,Callable接口中的call()方法有一個返回值,可以返回任務的執行結果,而Runnable接口中的run()方法是void的,沒有返回值。請看下面實例:

Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
  System.out.println("Asynchronous Callable");
  return "Callable Result";
}
});
System.out.println("future.get() = " + future.get());

如果任務執行完成,future.get()方法會返回Callable任務的執行結果。注意,future.get()方法會產生阻塞。

invokeAny(…)

invokeAny(…)方法接收的是一個Callable的集合,執行這個方法不會返回Future,但是會返回所有Callable任務中其中一個任務的執行結果。這個方法也無法保證返回的是哪個任務的執行結果,反正是其中的某一個。

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
  return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
  return "Task 2";
}
});
callables.add(new Callable<String>() {
  public String call() throws Exception {
  return "Task 3";
}
});
String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();

invokeAll(…)

invokeAll(…)與 invokeAny(…)類似也是接收一個Callable集合,但是前者執行之后會返回一個Future的List,其中對應著每個Callable任務執行后的Future對象。

List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
executorService.shutdown();

2. 在springBoot中使用java線程池ExecutorService

2.1 springBoot 的使用配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 數據收集配置,主要作用在于Spring啟動時自動加載一個ExecutorService對象.
 * @author Bruce
 * @date 2017/2/22
 * update by Cliff at 2027/11/03
 */
@Configuration
public class ThreadPoolConfig {
  @Bean
  public ExecutorService getThreadPool(){
    return Executors.newFixedThreadPool();
  }
}

2.2 使用

在@service 中注入 ExecutorService 然后就可以直接用了。
  @Autowired
  private ExecutorService executorService;
public void test(){
    executorService.execute(new Runnable() {
      public void run() {
        System.out.println("Asynchronous task");
      }
    });
  }

上述內容就是spring boot中怎么使用ExecutorService線程池,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

唐山市| 孟津县| 崇文区| 尼玛县| 桐城市| 大洼县| 武隆县| 谷城县| 社旗县| 南召县| 麻阳| 长顺县| 阜阳市| 大埔区| 菏泽市| 金湖县| 巩留县| 云梦县| 西藏| 珲春市| 苏尼特右旗| 清新县| 文安县| 阿城市| 百色市| 兴安县| 罗甸县| 武定县| 临城县| 兴隆县| 台北市| 鄯善县| 黔南| 湄潭县| 邻水| 泰安市| 松原市| 宜兴市| 天全县| 额尔古纳市| 中卫市|