【问题标题】:Task getting rejected although threads are available尽管线程可用,但任务被拒绝
【发布时间】:2016-05-11 19:22:08
【问题描述】:

我面临一个奇怪的情况,我有一个线程池,maxPoolSize 为 100,队列大小为 30,corePoolSize 为 50。应用程序重新启动一段时间后,我可以在日志中看到 RejectedExecution 错误,即使线程是可用,任务被拒绝。

org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@593a81ea[Running, pool size = 100, active threads = 3, queued tasks = 17, completed tasks = 57463]]

我多次进行线程转储,发现这个池的线程正在执行Timed_Waiting。上面的日志是正确的,根据转储也只有 3 个可运行,但我无法理解为什么其余 97 个线程对系统不可用。以下是 97 个线程常见的线程转储:

YYYThreadPoolExecutor-100" #6414 prio=5 os_prio=0 tid=0x00007f0830dce800 nid=0x3a39 waiting on condition [0x00007f064b6b5000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00007f0a32b21088> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)

系统是具有 100 GB RAM 的 16 核机器。 16 核的当前 CPU 利用率仅为 103%,RAM 利用率为

即使我也将线程池大小增加到 500,同样的情况也会延迟到来。

以前有人遇到过这种情况吗? 提前致谢。

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    参考oracle文档ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler)
    

    使用给定的初始参数和默认线程工厂创建一个新的 ThreadPoolExecutor。

    参数:

    corePoolSize - 保留在池中的线​​程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut

    maximumPoolSize - 池中允许的最大线程数

    keepAliveTime - 当线程数大于核心时,这是多余的空闲线程在终止前等待新任务的最长时间。

    unit - keepAliveTime 参数的时间单位

    workQueue - 用于在执行任务之前保存任务的队列。此队列将仅保存由 execute 方法提交的 Runnable 任务。

    handler - 由于达到线程边界和队列容量而阻塞执行时使用的处理程序

    根据您提供的详细信息,由于数量庞大,您尚未达到线程池边界,但您可能已达到队列容量

    您不需要高数量的线程数。相反,您可以增加队列容量。

    通常队列大小将被配置为更高的值来编号线程池大小。 maximumPoolSize 可以配置为您机器中的 CPU 内核数:Runtime.getRuntime().availableProcessors()

    【讨论】:

    • 嗨,当服务器重新启动时,我可以看到达到 100 个线程,即触及上限和活动线程 = 100,但在几秒钟内,活动线程突然下降到 5,我得到任务被拒绝。我进行了线程转储,但这些线程只是处于 TIMED_WAITING 状态,没有为任何监视器/IO 锁定。我不能将队列大小增加到超出限制,因为它会减慢我的系统,因为命中率很高。你知道那些线程可能在系统中但对系统不可用
    • 您可以发布您的代码以更好地理解吗? - ThreadPoolExecutor & Runnable/Callable 部分已经足够好了
    • 我无法粘贴整个代码,但如果有帮助,我可以给你一个简短的介绍。我有一个提交任务的线程池执行器。在这些任务中,会调用另一个线程池执行程序,并且在两个级别都存在倒计时锁存器。如果出现任何未处理的异常,我已经注意使用 finally 对锁存器进行倒计时。等待锁存器是时间驱动的。内部执行器从父任务中获得 8-9 次命中,这是被拒绝的任务。家长正常接受任务。
    • 如果你的队列容量是 30,你甚至不需要 30 个线程。绝对您正在达到队列容量,因此被拒绝执行处理程序。在增加工作队列的容量方面你有什么限制?
    猜你喜欢
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    相关资源
    最近更新 更多