【问题标题】:Task Getting rejected due to max pool size in ThreadPoolExecutor由于 ThreadPoolExecutor 中的最大池大小,任务被拒绝
【发布时间】:2018-12-04 12:35:28
【问题描述】:

应用程序已将 Zuul 和 Eureka 配置为将请求路由到后端服务,并且在我们进行负载测试之前一切正常。

我开始在我们的负载测试环境中执行 10 个并发请求,并在 zuul 网关中收到转发错误,原因是线程池无法为将来的任务分配线程并拒绝任务,并出现以下错误。

Caused by: java.util.concurrent.RejectedExecutionException: Task 
java.util.concurrent.FutureTask@70fe89b5 rejected from 
java.util.concurrent.ThreadPoolExecutor@25df1748[Running, pool size = 10, 
active threads = 10, queued tasks = 0, completed tasks = 1502]

我的奇迹;上述原因,我看到池大小只有 10 并且 10 个线程很忙,因为我连续发出 10 个请求,所以很实用。

但是我的 corepoolsize 应该比我在此处所经历的计数 10 大得多。是什么导致我的应用程序限制为 10 个池大小,我可以在我的应用程序中增加 corepoolsize 和 maxpoolsize。

【问题讨论】:

    标签: java multithreading threadpool threadpoolexecutor


    【解决方案1】:

    根据 javadocs,一个 RejectedExecutionException 可能会被 ThreadPoolExecutor 抛出,原因有几个:

    • 如果请求无法排队,并且无法创建另一个池线程,因为这将超过maxPoolSize

    • 如果shutdown()方法已经在执行器上被调用。

    现在您说您正在使用“默认”Java 执行程序,但您的意思有点不清楚。 (如果您向我们展示了您是如何获取和使用这个执行器的,您的问题会更容易理解!)

    但最重要的是,池大小不太可能是您的任务被拒绝问题的原因。如果所有工作人员都很忙,任务应该排队。


    但我看到池大小只有 10,这在现实 [生活] 场景中是不行的

    在许多现实生活场景中,池大小为 10 就可以了。但如果它不适合你的场景,你应该考虑创建一个更大(或更小)池的执行器。

    【讨论】:

    • 但是我看到池大小只有 10,这在实时场景中是不行的
    • 好的,我将实现自定义执行器。但是对于实时场景来说,10 是非常小的数字
    • IIRC,默认池大小是 JVM 可用处理器数量的函数。因此,它代表了现实生活场景的明智选择。 (本题与"real time"无关!!)
    • @pappu_kutty 池大小为 10 并不意味着您的应用程序不能处理超过 10 个并发请求。正如 StephenC 所说,所有请求都会被处理,它们可能会在队列中等待一段时间。
    • @ohlec,是的。应处理所有请求,但它们是否处于具有相同处理时间的并发场景中。我的问题是,我是否需要通过自定义实现来增加我的核心和最大池大小?
    【解决方案2】:

    问题是您使用的是哪个线程池? 您可以在 Java 中定义各种 ExecutorServices,例如用于未知线程数的缓存线程池,这将解决您的问题(我的一个项目的示例代码):

    ExecutorService pool = Executors.newCachedThreadPool();
        for(FluentCreate create: creates) {
            pool.execute(()->{
                try {
                    create.execute();
                } catch (JiraException | IOException | ParseException | RestException | URISyntaxException e) {
                    e.printStackTrace();
                }
            });
        }
    pool.shutdown();
    pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
    

    如果您能够预测使用固定线程池可以执行的任务数量。

    Executors.newFixedThreadPool(3);
    

    【讨论】:

    • 我们没有在我们的应用程序中明确定义任何线程池,我们将使用默认的 ThreadPoolExecutor。正如我在错误中显示的那样。
    • 这个 ThreadPoolExecutor 是 Zuul 定义的还是你定义的?抱歉,无法查看完整的堆栈跟踪。
    • 默认 Java 执行器
    • 能否给个密码。我认为我们在谈论不同的目的。 Java 中 ThreadPoolExecutor 的好例子:baeldung.com/thread-pool-java-and-guava
    • @pappu_kutty 没有默认的 Java 执行器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 2011-08-13
    • 1970-01-01
    相关资源
    最近更新 更多