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

标签 java multithreading threadpool executorservice

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

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

THREAD_POOL = Executors.newCachedThreadPool();

但如果不是实时的,我希望能够控制线程池的大小。 为此,我正在考虑 2 个选项,但我不太了解其中的区别,以及哪个会表现更好。

选项 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<Runnable>(10000), rejectHandler);

我想了解使用更复杂的选项 2 的优势是什么,以及我是否应该使用不同于 LinkedBlockingQueue 的其他数据结构?任何帮助将不胜感激。

最佳答案

查看源代码你会发现:

Executors.newFixedThreadPool(threadPoolSize);

等同于:

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

因为它没有提供明确的 RejectedExecutionHandler , 默认 AbortPolicy用来。它基本上抛出 RejectedExecutionException一旦队列已满。但是队列是无界的,所以它永远不会满。因此这个执行者接受无限1个任务。

您的声明要复杂得多且完全不同:

  • new LinkedBlockingQueue<Runnable>(10000)如果超过 10000 个正在等待,将导致线程池丢弃任务。

  • 我不明白你的意思RejectedExecutionHandler是在做。如果池发现它不能将更多的可运行对象放入队列,它会调用您的处理程序。在此处理程序中,您...尝试将 Runnable 放入再次进入队列(这将 在 99% 的情况下失败 block )。最后你吞下了异常。好像 ThreadPoolExecutor.DiscardPolicy就是你所追求的。

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

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

1 - 假设 2^31 是无穷大

关于java - 使用 Executors 服务在 Java 中创建固定大小线程池的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14286209/

相关文章:

java - 如何在 java 或 scala 中获取本地主机网络接口(interface)

Java netbeans 表单 - 从组合框中获取值

c# - 如何使委托(delegate)线程成为STA

C# 捕获 ThreadPool 上发生的异常

java - 如何在 Swing 中获取 JFrame

Java 小程序不再调用 public static void main()

c# - 如何为一个耗时的函数停止一个线程

c++ - 多线程。如何平等共享公共(public)资源?

c - 没有锁的一插入多读列表安全吗?

java - JVM 是否限制 Executor 可以运行的线程数量?