线程池
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveSize:空闲时间
- Timeunit:时间单位
- workQueue:等待队列
- RejectedExecutionHandler:拒绝策略
-
如果此时线程数小于核心线程数,那么就会新起一个线程来执行当前的任务。
-
如果此时线程数大于核心线程数,那么就会将任务塞入阻塞队列中,等待被执行。
-
如果阻塞队列满了,并且此时线程数小于最大线程数,那么会创建新线程来执行当前任务。
-
如果阻塞队列满了,并且此时线程数大于最大线程数,那么会采取拒绝策略。
线程执行
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
拒绝策略
- CallerRunsPolicy:使用调用者线程执行任务
- AbortPolicy:抛出异常,终止任务;默认拒绝策略
- DiscardPolicy:直接丢弃任务
- DiscardOldestPolicy:丢弃等待队列中最老的任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
等待队列是否可以采用无界队列
采用无界队列可能会存在以下问题:
- 首先由线程池原理可知,在等待队列满了之后会额外创建线程直到达到最大线程数,因此如果采用无界队列会导致maximumPoolSize参数失效
- 其次由于无界队列不会满,导致线程池也无法触发拒绝策略,大量任务堆积的情况下会导致任务执行时间过长
- 无界队列在大量任务存储无限制的情况下会导致JVM内存被撑爆