IDEA匯入阿里規約插件,當你這樣寫代碼時,插件就會自動監測出來,并給你紅線提醒,

告訴你手動創建執行緒池,效果會更好,
在探秘原因之前我們要先了解一下執行緒池 ThreadPoolExecutor 都有哪些引數及其意義,
ThreadPoolExecutor 構造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
//code…
}
引數的意義:
1.corePoolSize 指定了執行緒池里的執行緒數量,核心執行緒池大小
2.maximumPoolSize 指定了執行緒池里的最大執行緒數量
3.keepAliveTime 當執行緒池執行緒數量大于corePoolSize時候,多出來的空閑執行緒,多長時間會被銷毀,
4.unit 時間單位,TimeUnit
5.workQueue 任務佇列,用于存放提交但是尚未被執行的任務,
我們可以選擇如下幾種:
ArrayBlockingQueue:基于陣列結構的有界阻塞佇列,FIFO,
LinkedBlockingQueue:基于鏈表結構的有界阻塞佇列,FIFO,
SynchronousQueue:不存盤元素的阻塞佇列,每個插入操作都必須等待一個移出操作,反之亦然,
PriorityBlockingQueue:具有優先級別的阻塞佇列,
6.threadFactory 執行緒工廠,用于創建執行緒,一般可以用默認的
7.handler 拒絕策略,所謂拒絕策略,是指將任務添加到執行緒池中時,執行緒池拒絕該任務所采取的相應策略,
什么時候拒絕?當向執行緒池中提交任務時,如果此時執行緒池中的執行緒已經飽和了,而且阻塞佇列也已經滿了,則執行緒池會選擇一種拒絕策略來處理該任務,該任務會交給RejectedExecutionHandler 處理,
執行緒池提供了四種拒絕策略:
AbortPolicy:直接拋出例外,默認策略;
CallerRunsPolicy:用呼叫者所在的執行緒來執行任務;
DiscardOldestPolicy:丟棄阻塞佇列中靠最前的任務,并執行當前任務;
DiscardPolicy:直接丟棄任務;
阿里規約之所以強制要求手動創建執行緒池,也是和這些引數有關,具體為什么不允許,規約是這么說的:
執行緒池不允許使用Executors去創建,而是通過ThreadPoolExecutor的方式,這樣的處理方式讓寫的同學更加明確執行緒池的運行規則,規避資源耗盡的風險,
Executor提供的四個靜態方法創建執行緒池,但是阿里規約卻并不建議使用它,
Executors各個方法的弊端:
1)newFixedThreadPool和newSingleThreadExecutor:
??主要問題是堆積的請求處理佇列可能會耗費非常大的記憶體,甚至OOM,
2)newCachedThreadPool和newScheduledThreadPool:
??主要問題是執行緒數最大數是Integer.MAX_VALUE,可能會創建數量非常多的執行緒,甚至OOM,
看一下這兩種弊端怎么導致的,
第一種,newFixedThreadPool和newSingleThreadExecutor分別獲得 FixedThreadPool 型別的執行緒池 和 SingleThreadExecutor 型別的執行緒池,
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
因為,創建了一個無界佇列LinkedBlockingQueuesize,是一個最大值為Integer.MAX_VALUE的執行緒阻塞佇列,當添加任務的速度大于執行緒池處理任務的速度,可能會在佇列堆積大量的請求,消耗很大的記憶體,甚至導致OOM,
第二種,newCachedThreadPool 和 newScheduledThreadPool創建的分別是CachedThreadPool 型別和 ScheduledThreadPoolExecutorScheduledThreadPoolExecutor型別的執行緒池,
CachedThreadPool是一個會根據需要創建新執行緒的執行緒池 ,ScheduledThreadPoolExecutor可以用來在給定延時后執行異步任務或者周期性執行任務,
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
創建的執行緒池允許的最大執行緒數是Integer.MAX_VALUE,空閑執行緒存活時間為0,當添加任務的速度大于執行緒池處理任務的速度,可能會創建大量的執行緒,消耗資源,甚至導致OOM,
這兩種都是有點極端的,稍微點進去看一下原始碼就能看出來,
阿里規約提倡手動創建執行緒池,而非Java內置的執行緒池,給出的正例如下:
//org.apache.commons.lang3.concurrent.BasicThreadFactory
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern(“example-schedule-pool-%d”).daemon(true).build());
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(“demo-pool-%d”).build();
//Common Thread Pool
ExecutorService pool = new ThreadPoolExecutor(5, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
pool.execute(()-> System.out.println(Thread.currentThread().getName()));
pool.shutdown();//gracefully shutdown
//in code
userThreadPool.execute(thread);
IDEA安裝阿里規約插件,就能提示你不要這么使用,
滑鼠放上去,就會給你提示資訊,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/290245.html
標籤:java
上一篇:JAVA鎖機制
下一篇:JDK8的安裝配置
