我使用submit()方法将实现ExecutionService的可调用任务提交。很少情况下会出现死锁问题,但我无法确定它发生在何处或为何发生,因此我想在任务上设置超时,但不清楚如何做?
我的选择是:
1. 在提交任务时使用ExecutionService的invokeAny()方法而不是submit()并设置超时。我一次逐个提交许多任务使用submit(),我也可以像这样使用invokeAny()吗?我持谨慎态度,因为我无法理解为什么没有一个带有超时参数的submit()方法。 2. 修改ExecutorService的构造函数中的keepAliveTime(但我认为这做了其他事情)。 3. 修改实际的Callable实现,但如果它发生死锁,则无法解除死锁。
选择1似乎是唯一可行的解决方案,但这是真的吗?
更多细节:
我认为值得解释下过程的工作原理,以防它对解决方案有所帮助。
启动可调用任务P1后,它会在一个文件夹中运行,并处理其中的所有文件和文件夹,然后开始将歌曲分组。它在ExecutorService ES1中运行,并且只有一个P1实例提交到ES1中。
我们还有另外三个可调用类:P2、P3和P4。每个类都有自己的关联Executor Service,即ES2、ES3和Es4。一旦P1创建了一个组,它就会将一个任务提交到相关的ES,并将组作为数据传递。例如,它可以向E2提交P2实例,或向E4提交P3或P4实例,选择哪个取决于分组的细节,P2、P3和P4都执行不同的操作。
假设它已经提交了P2的一个实例,P2将通过向E3提交P3或向E4提交P4来完成处理。这是一个单向管道,P3只能提交给P4,一旦所有任务都已提交给P4并且P4完成了所有任务,则处理完成。
我们通过构建ES1、ES2、ES3和ES4来完成处理。先提交任务到P1,然后依次在每个ExecutorService上调用shutdown(),因此,在所有组都已提交完毕之前,shutdown()不会返回。然后在ES2上调用shutdown(),直到ES2清除了其P2任务队列为止。
很少情况下,一切都会突然停止,我认为某些进程正在阻止其他进程继续运行,所以现在我想要一种方法来取消需要太长时间的进程,以便其他进程可以继续。这比无限期地挂起要好得多。
我尝试使用建议的invokeAny(),它有点奏效。如果P1向E2提交P2的实例,则等待完成,这还可以接受,因为使用submit()时,它只是返回任何方式,不进行进一步处理,但有两个问题:
我的选择是:
1. 在提交任务时使用ExecutionService的invokeAny()方法而不是submit()并设置超时。我一次逐个提交许多任务使用submit(),我也可以像这样使用invokeAny()吗?我持谨慎态度,因为我无法理解为什么没有一个带有超时参数的submit()方法。 2. 修改ExecutorService的构造函数中的keepAliveTime(但我认为这做了其他事情)。 3. 修改实际的Callable实现,但如果它发生死锁,则无法解除死锁。
选择1似乎是唯一可行的解决方案,但这是真的吗?
更多细节:
我认为值得解释下过程的工作原理,以防它对解决方案有所帮助。
启动可调用任务P1后,它会在一个文件夹中运行,并处理其中的所有文件和文件夹,然后开始将歌曲分组。它在ExecutorService ES1中运行,并且只有一个P1实例提交到ES1中。
我们还有另外三个可调用类:P2、P3和P4。每个类都有自己的关联Executor Service,即ES2、ES3和Es4。一旦P1创建了一个组,它就会将一个任务提交到相关的ES,并将组作为数据传递。例如,它可以向E2提交P2实例,或向E4提交P3或P4实例,选择哪个取决于分组的细节,P2、P3和P4都执行不同的操作。
假设它已经提交了P2的一个实例,P2将通过向E3提交P3或向E4提交P4来完成处理。这是一个单向管道,P3只能提交给P4,一旦所有任务都已提交给P4并且P4完成了所有任务,则处理完成。
我们通过构建ES1、ES2、ES3和ES4来完成处理。先提交任务到P1,然后依次在每个ExecutorService上调用shutdown(),因此,在所有组都已提交完毕之前,shutdown()不会返回。然后在ES2上调用shutdown(),直到ES2清除了其P2任务队列为止。
很少情况下,一切都会突然停止,我认为某些进程正在阻止其他进程继续运行,所以现在我想要一种方法来取消需要太长时间的进程,以便其他进程可以继续。这比无限期地挂起要好得多。
我尝试使用建议的invokeAny(),它有点奏效。如果P1向E2提交P2的实例,则等待完成,这还可以接受,因为使用submit()时,它只是返回任何方式,不进行进一步处理,但有两个问题:
- 每个ExecutorService使用一个有界队列,大小为500,其想法是如果P2比P1慢得多,我们就不会将任务堆积到ES2上,最终耗尽内存。因此,现在P1直到调用的任务完成后才完成,队列实际上变小了,因为它们不仅由等待ES2上的插槽完成的任务组成,而且包含已经提交给ES2但正在等待其完成的任务。
- 流水线被链接起来,因此如果我们对从P1提交的任务、从P2和P3和P4提交的任务使用invokeAny,那么当从P1提交任务到P2时,它将不会返回,直到从E4完成后进行后续处理!