创建ThreadPoolExecutor可以通过构造方法和Executors的静态方法。
构造方法:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
corePoolSize,线程池里最小线程数
maximumPoolSize,线程池里最大线程数量,超过最大线程时候会使用RejectedExecutionHandler
keepAliveTime,unit,线程最大的存活时间
workerQueue,缓存异步任务的队列
threadFactory,用来构造线程池里的worker线程
线程池提交任务流程,以下代码有简化
Runnable command
if (workerCount < corePoolSize) {
new Worker().run(command);
workerCount++
}
if (workerQueue.offer(command)) { //入队
// 还没达到maximumPoolSize 创建worker
new Worker();
workerCount++;
} else if (!addWorker(command)) { //还没达到maximumPoolSize,创建worker并运行
handler.rejectedException(command)
}
线程池中线程不足corePoolSize的时候直接创建线程运行command,不然的话提交到队列,其他worker会对这个队列做poll。
当workerQueue队列满了的时候,会创建新的worker,如果worker达到上限会调用handler.rejectedException方法。
Executors.newCachedThreadPool
core是0,max是无限,队列是SynchronousQueue。无限创建线程,线程60S过期被销毁。风险点是线程数不可控。
Executors.newFixedThreadPool
core是thread数量,max是thread数量,队列是LinkedBlockingQueue。因为LinkedBlockingQueue是无界的,所以max不会起作用。风险点是workerQueue的长度不可控
关于ThreadPoolExecutor.DiscardPolicy和ThreadPoolExecutor.CallerRunsPolicy
一个是队列慢了就丢弃。一个是队列满了就使用主线程来执行,变成同步调用的方式。主线程就是调用submit方法的线程。
我的任务是请求外部HTTP链接,且允许失败,我希望不要影响其他线程。
使用线程池的参数:
new ThreadPoolExecutor(
10, 100, 60, TimeUnit.SECONDS, //限制最大线程,如果是CPU密集型的任务,核心线程就用核数,最大线程就用核数的N倍
new ArrayBlockingQueue<Runnable>(1000), //固定大小,防止内存堆积过多
new NamedThreadFactory("third_retrieval"), //自己的ThreadFactory
new ThreadPoolExecutor.DiscardPolicy()) //当任务对接的时候直接丢弃