有 Java 编程相关的问题?

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

多线程Java线程池任务执行队列

当通过ThreadPoolExecutor使用java线程池时,所有任务在执行前是否都已排队?或者,它们是否仅在没有可用线程时排队(正在运行的线程数等于或大于核心池大小)


共 (1) 个答案

  1. # 1 楼答案

    任务提交者总是将任务发送到队列(或尝试),因为它们与池线程之间没有直接联系(,而且有充分的理由

    enter image description here

    无限队列

    关于您的问题,即使线程可用,任务也会首先插入队列,然后由choosen free线程拉入。如果没有可用线程,提交者仍会将任务放入队列。 在resume中,流总是Submitter -> Queue -> Thread

    无界队列通常定义整数的最大大小。最大_值,在99%的时间内足以避免提交程序阻塞

    大小有限的队列

    如果队列中没有可用的位置,提交者可以实现不同的机制,例如:

    • 调用方运行:其中提交方是运行任务的人
    • 阻塞行为:提交者可能会尝试将任务插入队列(永久或在超时内,然后丢弃)
    • 放弃策略:如果尝试插入新任务,可以将队列配置为删除最旧的排队任务

    无论使用何种机制,任务流程(如果一切正常)都是:

    Submitter -> Queue -> Thread

    在更糟糕的情况下,这种流动可能是:

    Submitter > Submitter(队列已满且调用方运行)

    Submitter > Queue > GarbageCollector(队列已满,已丢弃,因为这是最古老的任务)

    Submitter > GarbageCollector(队列已满,重试失败后丢弃)


    在任何情况下,流量都不会被忽略

    Submitter > Thread

    避免提交者和线程池之间的直接连接使该系统具有异步性质,其中队列代表“安全窗口”。 这样:

    • Submitters从未被阻塞(使用无界队列
    • ^只有当队列已满且机制实现了阻塞行为时,{}才会被阻塞(使用有界队列
    • Threads不必处理任务提交者的直接同步请求
    • SubmittersThreads避免复杂的同步机制,因为它们不必直接协商
    • 如果Submitters因某个错误而停止或被交付停止,Threads仍可以通过提取挂起的排队任务继续工作
    • 同样,如果Threads被停止,Submitters仍然可以继续工作,将任务放置在queue中以备将来处理(使用无限队列)

    考虑到这一点,监控queue的内容及其最大大小非常重要,这是为了避免OOM异常。如果提交者发送太多任务和/或太快,而线程无法遵循其节奏,则可能会发生这种情况。这将涉及队列内部的上升延迟,因此可能出现Out of Memory错误