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

首頁 > 開發 > Java > 正文

在spring boot中使用java線程池ExecutorService的講解

2024-07-14 08:43:37
字體:
來源:轉載
供稿:網友

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 */@Configurationpublic 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");      }    });  }

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 缙云县| 库车县| 怀来县| 博爱县| 汉寿县| 万全县| 化州市| 寿宁县| 新绛县| 黄浦区| 那曲县| 镇康县| 崇左市| 宜兰县| 合肥市| 拜泉县| 昌吉市| 丹阳市| 长海县| 咸阳市| 长乐市| 新源县| 泰来县| 庆元县| 湘乡市| 云梦县| 新密市| 许昌县| 樟树市| 建始县| 东兴市| 罗定市| 大新县| 多伦县| 南木林县| 海南省| 香港| 名山县| 乌兰察布市| 高清| 汾阳市|