摘要:我正在尝试使用ThreadPoolExecutor并行化我的系统,并且遇到了死锁问题。我知道为什么会遇到这个问题,但是我对Java上下文中的并发不是很熟悉,所以我不确定要使用什么类/方法:

一个简单的例子:我的代码解析了一个类似xml的大树,然后为顶级指令生成了一个线程。该线程运行;执行时,它会读取更多的xml树,并在同一ThreadPoolExecutor上生成更多线程(我使用1个池,因为存在用户定义的最大值)。直到XML树被消耗掉为止。

当足够多的父线程最终进入线程池并且它们的所有子线程仍在队列中时,它们将死锁(因为父线程在未运行的子线程上被阻塞)。假设我的树是

Parent thread
 Child Thread A
  Child Child Thread A1
  Child Child Thread A2
  Child Child Thread A3
 Child Thread B
 Child Thread C

现在,我将使用父线程,A,B,C,A1,A2和A3作为线程。假设我的最大线程池为2。这意味着,按照解析的方式,P,A在线程池中,其他所有内容在线程队列中。

在这里,每个非叶节点都将在叶节点上被阻塞。由于叶子节点是最后解析的,因此它们甚至不在线程池中(而是在队列中)。因此,叶子的 child 永远不会运行,整个系统陷入僵局。

问题:是否有一些方法调用可在创建子线程后立即将父线程踢出正在运行的线程池?我对使用回调保持警惕,因为我的系统可以选择启动并发,所以我真的不想在子类上打乱代码以回调可能根本不存在的父线程。

另外,我应该如何实现某种线程队列选择算法(优先级/时钟/等); ThreadPoolExecutor是要使用的正确类吗?

谢谢。

最佳答案

如果您需要诸如“等待线程”之类的东西来等待子线程完成直到他们完成工作,请查看 java.util.concurrent.ForkJoinPool 。它允许您从父任务中生成子任务。尽管父任务必须等待,但它们不会阻塞任何线程。

任务本身是通过将 java.util.concurrent.RecursiveTask 子类化来实现的。您还可以在JavaDoc中找到一个代码示例。

也许从Oracle's tutorial about Fork/Join开始!

关于java - 死锁/w ThreadPoolExecutor,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21096507/

10-14 17:02
查看更多