参数最全的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
解释: corePoolSize 核心线程池大小, maximumPoolSize 大小,BlockingQueue 阻塞队列,多余的任务会放在这, ThreadFactory 生产线程池的线程, RejectedExecutionHandler 拒绝策略
while (task != null || (task = getTask()) != null)
的条件为真,第一次判断时task为firstTask,即执行的第一个任务,那么要点就成了getTask()必须不能为空getTask()中有个核心逻辑是:
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
这里的workQueue就是阻塞队列,timed表示是否会超时释放,keepAliveTime是非核心线程允许的空闲时间;如果不超时,则调用BlockingQueue.take(),如果取不到值,就会一直阻塞直到程序提交了一个任务。所以,阻塞队列的作用是控制线程池中线程的生命周期。
所以阻塞队列保证了,线程池中的线程不会被回收,达到线程复用的目的。
因为添加任务调用的并不是阻塞的put()方法,而是非阻塞的offer()方法。 所以需要用拒绝策略。
所以线程池具有是生产者不阻塞,而消费者阻塞的特点。
有界队列:
ArrayBlockingQueue
无界队列:
LinkedBlockingQueue Executors.newFixedThreadPool() 采用的阻塞队列,因为是无界的,某些情况下会导致队列容量扩大,内存飙升
同步移交队列:
SynchronousQueue 不存储元素,只是移交
优先级队列:
PriorityBlockingQueue 具有优先级
延迟队列
DelayedWorkQueue
4种策略都做为静态内部类在ThreadPoolExcutor中进行实现。
AbortPolicy
中止策略 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
使用该策略时在饱和时会抛出RejectedExecutionException(继承自RuntimeException),调用者可捕获该异常自行处理。
DiscardPolicy
抛弃策略 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
如代码所示,不做任何处理直接抛弃任务
DiscardOldestPolicy
抛弃旧任务策略
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
如代码,先将阻塞队列中的头元素出队抛弃,再尝试提交任务。如果此时阻塞队列使用PriorityBlockingQueue优先级队列,将会导致优先级最高的任务被抛弃,因此不建议将该种策略配合优先级队列使用。
CallerRunsPolicy
调用者运行
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
既不抛弃任务也不抛出异常,直接运行任务的run方法,换言之将任务回退给调用者来直接运行。使用该策略时线程池饱和后将由调用线程池的主线程自己来执行任务,因此在执行任务的这段时间里主线程无法再提交新任务,从而使线程池中工作线程有时间将正在处理的任务处理完成。
都在Executors下面
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue(),
threadFactory);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
//
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory);
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
下面列出了 Executor 和 ExecutorService 的区别:
Executor | ExecutorService
Executor 是 Java 线程池的核心接口,用来并发执行提交的任务 ExecutorService 是 Executor 接口的扩展,提供了异步执行和关闭线程池的方法
Executor提供execute()方法用来提交任务
ExecutorService提供submit()方法用来提交任务
Executor execute()方法无返回值
ExecutorService submit()方法返回Future对象,可用来获取任务执行结果
Executor 不能取消任务
ExecutorService 可以通过Future.cancel()取消pending中的任务
Executor没有提供和关闭线程池有关的方法
ExecutorService 提供了关闭线程池的方法
而Executors是一个类,工具类。Executors和Executor类似于Collections和Collection的关系。
参考链接:
https://segmentfault.com/a/1190000014417569
https://zhuanlan.zhihu.com/p/32867181
https://yemengying.com/2017/03/17/difference-between-executor-executorService/