使用Executors服务在Java中创建固定大小线程池的最佳方法

我使用Java中的Executors框架为multithreading应用程序创建线程池,我有一个与性能相关的问题。

我有一个可以在实时或非实时模式下工作的应用程序。 如果它是实时的,我只是使用以下内容:

 THREAD_POOL = Executors.newCachedThreadPool(); 

但是,如果它不是实时的,我希望能够控制我的线程池的大小。 要做到这一点,我正在考虑两个选项,但我并不真正理解其中的差异,哪个会更好。

选项1是使用简单的方法:

 THREAD_POOL = Executors.newFixedThreadPool(threadPoolSize); 

选项2是创建我自己的ThreadPoolExecutor如下所示:

 RejectedExecutionHandler rejectHandler = new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { try { executor.getQueue().put(r); } catch (Exception e) {} } }; THREAD_POOL = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue(10000), rejectHandler); 

我想了解使用更复杂的选项2的优点是什么,以及我是否应该使用另一个数据结构而不是LinkedBlockingQueue ? 任何帮助,将不胜感激。

查看源代码,您将意识到:

 Executors.newFixedThreadPool(threadPoolSize); 

相当于

 return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, MILLISECONDS, new LinkedBlockingQueue()); 

由于它不提供显式的RejectedExecutionHandler ,因此使用默认的AbortPolicy 。 一旦队列满了,它基本上会抛出RejectedExecutionException 。 但是队列是无限的,因此永远不会满员。 因此,此执行程序接受1个任务数量。

你的声明要复杂得多,而且完全不同:

  • new LinkedBlockingQueue(10000)将导致线程池在等待超过10000的任务时丢弃任务。

  • 我不明白你的RejectedExecutionHandler在做什么。 如果池发现它不能再将任何runnables放入队列,它就会调用你的处理程序。 在这个处理程序中,你…尝试将该Runnable再次放入队列中(这将是 在99%的情况下都失败了 块)。 最后你吞下了这个例外。 看起来像ThreadPoolExecutor.DiscardPolicy就是你所追求的。

    如果任务队列太大,看下面的评论似乎是你试图阻止或以某种方式限制客户端。 我不认为在RejectedExecutionHandler阻塞是个好主意。 而是考虑CallerRunsPolicy拒绝策略。 不完全相同,但足够接近。

总结:如果你想限制挂起任务的数量,你的方法几乎是好的。 如果你想限制并发线程的数量,第一个单线程就足够了。

1 – 假设2 ^ 31是无穷大