执行人#的newFixedThreadPool:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
执行人#newCachedThreadPool:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
为什么两个threadPool使用不同的Queue? 我查找了关于LinkedBlockingQueue和SynchronousQueue的java文档,但我仍然不知道为什么在这里使用它们,是考虑性能还是其他人?
答案 0 :(得分:1)
答案在ThreadPoolExecutor类的文档中:
- 队列
- 任何{@link BlockingQueue}都可用于转移和保留
- 提交的任务。此队列的使用与池大小调整交互:* *
* *
* *在那里 排队的三种常规策略:* * *- 如果运行的线程少于corePoolSize线程,则Executor *总是更喜欢添加新线程*而不是 排队。
* *- 如果corePoolSize或更多线程正在运行, Executor *总是更喜欢排队请求而不是添加 new * thread。
* *- 如果请求无法排队,则为新的 除非*这将超过maximumPoolSize,否则创建线程 在哪种情况下,任务将被拒绝。
* *- 直接切换。工作*队列的一个很好的默认选择是 {@ link SynchronousQueue}将任务交给线程 * 否则抱着他们。在这里,尝试排队任务*将失败 如果没有线程可以立即运行它,那么一个*新线程 将被建造。 *处理集时,此策略可避免锁定 可能具有内部依赖性的请求。 *直接切换 通常需要无限制的maximumPoolSizes来避免拒绝 新提交的任务。这反过来也承认了*的可能性 当命令继续*平均到达时,无限制的线程增长 比他们处理的速度快。
* *- 无界限 队列。 使用无界队列(例如{@link} LinkedBlockingQueue} 没有预定义的*容量)将导致新的 当所有* corePoolSize线程都忙时,在队列中等待的任务。 因此,只会创建corePoolSize *线程。 (和 因此,maximumPoolSize *的值没有任何值 当*每个任务完全时,这可能是合适的 独立于其他人,所以任务不能*影响彼此 执行;例如,在网页服务器中。 *虽然这种风格 排队可以用于平滑*瞬态突发 请求,它承认*无限制的工作队列增长的可能性 当命令继续以比平均值更快的速度到达时 处理。
* *- 有界队列。有界队列 (例如,* {@link ArrayBlockingQueue})有助于防止资源 当*与有限maximumPoolSizes一起使用时耗尽,但可以更多 难以调整和控制。队列大小和最大池大小 可以互相交换*使用大队列和小队列 池最小化* CPU使用率,OS资源和上下文切换 开销,但可能*导致人为的低吞吐量。如果任务 经常阻塞(例如,如果它们是I / O绑定的话),系统可以 能够安排*时间以获得比您允许的更多线程。 使用小队列*通常需要更大的池大小 保持CPU更忙,但*可能会遇到不可接受的调度 开销,也*降低吞吐量。
实际上,第一种类型的队列会立即向可用线程发送一个新的Runnable,如果所有线程都忙,第二种类型会保留它。