Java:使用可调整的ThreadPoolExecutor

时间:2018-01-20 09:43:38

标签: java multithreading thread-safety threadpoolexecutor

我想实现单生产者 - 多消费者逻辑,其中每个消费者处理时间取决于硬件响应。

**编辑

我有一组对象(设备)。每个对象(设备)对应于我想在软件中模拟的硬件实际单元。 我的主类将任务列表分发给每个设备。每个任务都需要一定的时间才能完成 - 我想控制它,以模拟硬件操作。每个设备对象都有自己的SingleThreadExecutorService服务执行程序来管理自己的排队任务。特定设备对象的任务上的Sleep不应干扰主设备或其他设备对象的性能。

到目前为止,事情正在发挥作用,但我不知道如何在没有阻塞主线程的情况下从任务中获得未来(!future.isDone())。当我这样做时,会出现两个问题:

  • 任务1已提交至device[ 1 ].executor。任务1休眠以模拟硬件操作时间。
  • 任务2应在提交任务1后立即提交给device[ 2 ].executor,但它不会,因为主线程保持while等待任务1返回{{1} }}。此问题会累积模拟延迟,因为添加的每个任务都会导致下一个设备必须等待上一个设备完成,而不是同时运行。delay propagation example

橙色线表示强制设备等待1000毫秒的命令。 当Future返回时,它会向设备2提交一个新任务,但它已经晚了1秒,见蓝线。依此类推,绿线显示延迟增量。

如果我没有使用Future来完成任务,模拟似乎正确运行。我无法找到使用future.isDone()的方法而无需创建新线程来检查它。此外,如果有人可以建议我如何继续这种情况,我真的很高兴。

1 个答案:

答案 0 :(得分:1)

如果您的目标是在处理任务期间实现每个消费者任务与硬件设备通信的内容,则任务的run方法应该只与设备通信并阻塞,直到它收到来自设备的响应。 (你如何做到这将取决于设备及其API ...)

如果您的目标是使用模拟设备执行上述操作(即出于测试目的),则让任务调用Thread.sleep(...)来模拟设备响应所需的时间。

根据您的问题描述(据我所知),您找到的PausableSchedulerThreadPoolExecutor课程无济于事。该类的作用是暂停线程本身。所有这些。

<强>更新

  

任务2应在提交任务1后立即提交给设备[2] .executor,但不会,因为主线程在等待任务1返回Future时保持不变

这是不正确的。在提交任务时立即返回Future对象。

你错误(可能)是主线程在get上调用Future。那会阻止。但问题是,在提交下一个任务之前,您的主线程实际上需要get上调用Future,然后它基本上是单线程的。

真正的解决方案:弄清楚如何打破使应用程序单线程化的依赖性。 (但要注意:如果将Future作为参数传递给任务,则相应的工作线程可能会阻塞。除非线程池中有足够的线程,否则最终会导致饥饿并降低并发性。)