一般我们创建Java线程池喜欢调用的api是下面这个样子的:
newCachedThreadPool | 自增长线程 |
newFixedThreadPool | 固定线程 |
newSingleThreadExecutor | 单线程 |
NewScheduledThreadPool | 定时线程 |
newWorkStealingPool | 考虑多cpu的并行情况,把线程再fork成子线程,然后join子线程结果,合并,有些MapReduce的思想 |
前4种线程池都是
ThreadPoolExecutor的api实现的:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
5种参数的组合也就形成了上面的几种线程池的功能:
参数名 | 作用 |
corePoolSize | 核心线程池大小,初始线程数量 |
maximumPoolSize | 最大线程池大小,当线程数量达到corePoolSize,没有达到workQueue有界队列的限制,又需要更多线程时,新申请的线程数量+corePoolSize 能达到最大限制数量 |
keepAliveTime | 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程也有有效时间 |
TimeUnit | keepAliveTime时间单位 |
workQueue | 阻塞任务队列,决定线程池的类型 |
threadFactory | 新建线程工厂,创建线程的工厂 |
RejectedExecutionHandler | 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理 |
几个参数的流程:
RejectedExecutionHandler的几种策略:
策略 | 说明 |
ThreadPoolExecutor.AbortPolicy() | 抛出java.util.concurrent.RejectedExecutionException异常 |
ThreadPoolExecutor.CallerRunsPolicy() | 重试添加当前的任务,他会自动重复调用execute()方法 |
ThreadPoolExecutor.DiscardOldestPolicy() | 抛弃旧的任务 |
ThreadPoolExecutor.DiscardPolicy() | 抛弃当前的任务 |
newWorkStealingPool:
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
使用ForkJoinPool实现,适合长时任务,对顺序无要求,其实是1.7的东西,旧瓶装新酒啊,哈哈哈
参考文献:
https://www.cnblogs.com/yyy-blog/p/10616531.html