ThreadPoolExecutor 的使用
線程池使用代碼如下:
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 10, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue(100));
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
// 執行線程池
System.out.println("test...");
}
});
ThreadPoolExecutor說明
ThreadPoolExecutor 構造方法有以下四個,如下圖所示:
其中最後一個構造方法有 7 個構造參數,包含了前三個方法的構造參數,這 7 個參數名稱如下所示:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
//...
}
其代表的含義如下:
-
① corePoolSize
線程池中的核心線程數,默認情況下核心線程一直存活在線程池中,如果將 ThreadPoolExecutor 的 allowCoreThreadTimeOut 屬性設爲 true,如果線程池一直閒置並超過了 keepAliveTime 所指定的時間,核心線程就會被終止。 -
② maximumPoolSize
線程池中最大線程數,如果活動的線程達到這個數值以後,後續的新任務將會被阻塞(放入任務隊列)。 -
③ keepAliveTime
線程池的閒置超時時間,默認情況下對非核心線程生效,如果閒置時間超過這個時間,非核心線程就會被回收。如果 ThreadPoolExecutor 的 allowCoreThreadTimeOut 設爲 true 的時候,核心線程如果超過閒置時長也會被回收。 -
④ unit
配合 keepAliveTime 使用,用來標識 keepAliveTime 的時間單位。 -
⑤ workQueue
線程池中的任務隊列,使用 execute() 或 submit() 方法提交的任務都會存儲在此隊列中。 -
⑥ threadFactory
爲線程池提供創建新線程的線程工廠。 -
⑦ rejectedExecutionHandler
線程池任務隊列超過最大值之後的拒絕策略,RejectedExecutionHandler 是一個接口,裏面只有一個 rejectedExecution 方法,可在此方法內添加任務超出最大值的事件處理。ThreadPoolExecutor 也提供了 4 種默認的拒絕策略:- new ThreadPoolExecutor.DiscardPolicy():丟棄掉該任務,不進行處理
- new ThreadPoolExecutor.DiscardOldestPolicy():丟棄隊列裏最近的一個任務,並執行當前任務
- new ThreadPoolExecutor.AbortPolicy():直接拋出 RejectedExecutionException 異常
- new ThreadPoolExecutor.CallerRunsPolicy():既不拋棄任務也不拋出異常,直接使用主線程來執行此任務
自定義線程池以及拒絕策略
直接上代碼吧…
package cn.fxbin.learn.config;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import java.util.concurrent.*;
/**
* ThreadPoolConfig
*
* @author fxbin
* @version v1.0
* @since 2019/12/17 0:59
*/
@Slf4j
@Configuration
public class ThreadPoolConfig {
private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;
private static final RejectedExecutionHandler DEFAULT_HANDLER = new ReTryAndLogPolicy();
@Bean(value = "queueThreadPool")
public ExecutorService queueThreadPool(){
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("queue-thread-%d").build();
ExecutorService pool = new ThreadPoolExecutor(4, 17, 60, DEFAULT_TIME_UNIT,
new ArrayBlockingQueue<Runnable>(1000),namedThreadFactory, DEFAULT_HANDLER);
return pool ;
}
/**
* ReTryAndLogPolicy
*
* 參考:
* <p>
* 1. CallerRunsPolicy :這個策略重試添加當前的任務,他會自動重複調用 execute() 方法,直到成功。
* 2. AbortPolicy :對拒絕任務拋棄處理,並且拋出異常。
* 3. DiscardPolicy :對拒絕任務直接無聲拋棄,沒有異常信息。
* 4. DiscardOldestPolicy :對拒絕任務不拋棄,而是拋棄隊列裏面等待最久的一個線程,然後把拒絕任務加到隊列。
* </p>
*
* @author fxbin
* @since 2019/12/17 0:59
*/
public static class ReTryAndLogPolicy extends ThreadPoolExecutor.CallerRunsPolicy {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
super.rejectedExecution(r, executor);
ThreadFactory factory = executor.getThreadFactory();
String threadNamePrefix = "";
if (factory.getClass() == CustomizableThreadFactory.class) {
CustomizableThreadFactory factory1 = (CustomizableThreadFactory) factory;
threadNamePrefix = factory1.getThreadNamePrefix();
}
log.info("executor info:{}", executor.toString());
log.error("threadNamePrefix {}, corePoolSize {}, maxPoolSize {}, workQueueSize {}, rejected task {}.",
new Object[]{threadNamePrefix, executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getQueue().size(), r.toString()});
}
}
}
歡迎關注博主公衆號
: