IO /网络绑定的Fork / Join-Tasks

时间:2012-01-30 22:01:07

标签: java scala concurrency deadlock task

我正在使用一个无限制的线程缓存Java-ExecutorService,它同时处理我的任务。 现在我有一些任务只执行一些冗长的操作(少数)和一些阻塞IO的任务(连接到URL,大多数)。 如果运行我的应用程序并启动一个工作负载,则会向执行程序分派大约70个任务,这些任务会激活70个线程并同时处理所有这些任务。

我想限制任务想要连接的每个主机的线程,如果可能,还要限制总体任务的数量。我的问题是所有任务都执行fork-join之类的操作,因此它们会产生其他任务并在继续之前等待其结果。这意味着我不能只为每个主机使用一个信号量或一个有界队列,因为任务可以分叉其他任务,直到信号量/队列有一个空闲槽才会得到处理,因此应用程序死锁。

是否有某种模式可以解决这个问题?

精炼:提交IO(=网络) - 绑定任务。在完成一些IO工作后,他们可能会分叉其他IO-Bound任务,然后加入它们,并可能进行额外的IO绑定处理。

这似乎是使用IO绑定任务的Fork / Join。如何限制/限制IO执行任务的执行而不会使最初分叉任务的线程死锁(死锁,因为分叉的子任务因限制/限制而不会被处理)?

非常感谢

3 个答案:

答案 0 :(得分:2)

为什么不使用scala actor库? 如果要使用池,还可以限制线程池大小。试试看: How to designate a thread pool for actors

答案 1 :(得分:2)

不幸的是,我不认为你的问题一般是可以解决的。如果我理解正确,你想将一些任务提交给线程数量的线程池,对吗?然后,每个任务可以阻止IO,提交一些额外的任务,然后再次阻止他们加入,对吗?

嗯,我担心在这种情况下僵局是不可避免的。所有线程池的线程可能在等待“分叉”任务运行的某个任务中被占用阻塞,但是,当然,它不能因为池耗尽而被占用。除了允许创建更多线程(无限制池)之外,没有办法解决它。

你可以做的是在启动期间稍微限制提交(在每个提交到池之间稍微休眠一下)。

答案 2 :(得分:2)

Async肯定是要走的路,因为它们构成非常好。虽然编程模型在Java中很痛苦,但在Scty上使用Finagle对于Scala来说是轻而易举的,其中所有操作基本上都是一个函数,它接受一个Request并返回一个可以映射(转换)的Future [Response]对面。

另见: