为什么在创建FixedThreadPool和CachedThreadPool时使用不同的Queue?

时间:2016-01-17 08:36:34

标签: java multithreading

执行人#的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? 我查找了关于LinkedBlockingQueueSynchronousQueue的java文档,但我仍然不知道为什么在这里使用它们,是考虑性能还是其他人?

1 个答案:

答案 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,如果所有线程都忙,第二种类型会保留它。