1. 程式人生 > >SpringBoot 執行緒池使用

SpringBoot 執行緒池使用

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;     }

    1     2     3     4     5     6     7     8     9     10     11     12     13     14     15     16     17     18     19     20     21     22     23     24     25     26     27     28     29     30     31     32     33     34     35     36     37     38     39     40     41     42     43     44     45     46     47     48     49     50     51     52     53     54     55     56     57     58     59     60     61

主要引數

    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();

    1     2     3     4     5     6     7

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.

    1     2     3     4     5     6     7     8

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());

    1     2     3     4     5     6     7     8

如果任務執行完成,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();

    1     2     3     4     5     6     7     8     9     10     11     12     13     14     15     16     17     18     19     20     21     22     23

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();

    1     2     3     4     5     6     7

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();     } }

    1     2     3     4     5     6     7     8     9     10     11     12     13     14     15     16     17     18     19     20     21     22

2.2 使用

在@service 中注入 ExecutorService 然後就可以直接用了。

    @Autowired     private ExecutorService executorService;

public void test(){         executorService.execute(new Runnable() {             public void run() {                 System.out.println("Asynchronous task");             }         });     } --------------------- 作者:雙斜槓少年 來源:CSDN 原文:https://blog.csdn.net/u012373815/article/details/78956225 版權宣告:本文為博主原創文章,轉載請附上博文連結!