有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

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

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


共 (1) 个答案

  1. # 1 楼答案

    查看源代码,您会发现:

    Executors.newFixedThreadPool(threadPoolSize);
    

    相当于

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

    因为它不提供显式的RejectedExecutionHandler,所以使用默认的AbortPolicy。一旦队列满了,它基本上会抛出RejectedExecutionException。但是队列是无限的,所以永远不会满。因此,该执行者接受inifnite1个任务

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

    • 如果等待的任务超过10000个,则new LinkedBlockingQueue<Runnable>(10000)将导致线程池放弃任务

    • 我不明白你的RejectedExecutionHandler在做什么。如果池发现无法将更多可运行程序放入队列,它将调用您的处理程序。在这里你。。。尝试再次将Runnable放入队列(在99%的情况下,会失败)。最后你接受了这个例外。看起来ThreadPoolExecutor.DiscardPolicy就是你想要的

      如果任务队列太大,查看下面的评论似乎是在试图阻止或以某种方式限制客户端。我不认为在RejectedExecutionHandler内屏蔽是个好主意。取而代之的是考虑{{CD9}}拒绝策略。不完全一样,但足够近

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

    1-假设2^31为无穷大