0

getQueue() 方法提供了对 ThreadPoolExecutor 中底层阻塞队列的访问,但这似乎并不安全。

遍历此函数返回的队列可能会错过 ThreadPoolExecutor 对队列所做的更新。

“方法 getQueue() 允许访问工作队列以进行监视和调试。强烈建议不要将此方法用于任何其他目的。”

如果你想遍历 ThreadPoolExecutor 使用的 workQueue,你会怎么做?还是有替代方法?

这是……的延续。 为生产者消费者问题的变体选择数据结构

现在,我正在尝试多生产者多消费者,但我想使用一些现有的线程池,因为我不想自己管理线程池,而且我想要在 ThreadPoolExecutor 完成执行某些任务时回调以及检查的能力以线程安全的方式“进行中的事务”数据结构。

4

3 回答 3

1

您可以覆盖 beforeExecute 和 afterExecute 方法,让您知道任务已经开始和完成。您可以覆盖 execute() 以了解何时添加任务。

您遇到的问题是队列不是为查询而设计的,并且可以在您看到之前使用任务。解决此问题的一种方法是创建自己的队列实现(可能覆盖/包装 ConcurrentLinkedQueue)

顺便说一句:队列是线程安全的,但不能保证您会看到每个条目。

ConcurrentLinkedQueue.iterator() 记录为

以正确的顺序返回此队列中元素的迭代器。返回的迭代器是一个“弱一致”迭代器,它永远不会抛出 ConcurrentModificationException,并保证遍历迭代器构造时存在的元素,并且可能(但不保证)反映构造之后的任何修改。

于 2011-05-09T10:22:15.817 回答
1

如果您希望复制队列中的项目并确保队列中的内容尚未执行,您可以尝试以下操作:

a) 引入暂停和恢复执行的能力。请参阅:http: //download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html

b) 首先暂停队列,然后复制队列,然后恢复队列。

And then i have my own question. The problem i see is that while you execute your "Runnable", that "Runnable" is not placed in the queue, but a FutureTask "wrapper", and i cannot find any way to determine just which one of my runnables i'm looking at. So, grabbing and examining the queue is pretty useless. Does anybody know aht i missed there?

于 2011-05-19T21:13:03.333 回答
0

如果您在上一个问题中接受的答案中遵循 Jon Skeet 的建议,那么您将通过锁控制对队列的访问。如果您在进行中的队列上获得了锁,那么您可以保证遍历不会错过其中的任何项目。

当然,这样做的问题是,当您进行遍历时,队列上的所有其他操作(其他生产者和消费者试图访问它)都会阻塞,这可能会对性能产生非常可怕的影响。

于 2011-05-09T10:30:29.290 回答