1

我有一个调用,从用户那里接收作业列表,说用户发布了 3 个作业 A、B 和 C,它们都开始在自己的线程 AT、BT 和 CT 中执行,然后我开始监视这 3 个线程,如果其中一个作业失败说 B 失败,我需要通知 A 和 C 停止。当所有线程停止时返回,当所有线程失败时全部为真,如果一个失败为假。

目前我有一个大的 while 循环,它会检查并休眠 50 毫秒,这很有效,但我想知道我是否有更好的方法可以在没有任何睡眠的情况下做到这一点,我尝试休眠 0 毫秒 AFAIK 这让我的线程结束cpu que,但它仍然使用了太多的 cpu,大约 60%。

4

3 回答 3

3

这听起来像是一个用例ExecutorCompletionService

// wrap tasks A, B and C into runnables (or callables if you need some result):
Callable<Result> taskA = ...;
Callable<Result> taskB = ...;
Callable<Result> taskC = ...;

// create an ExecutorCompletionService
// to which you must pass an ExecutorService
// (choose one according to your precise use case)
// (the newCachedThreadPoolExecutor might not be a sensible choice)
ExecutorCompletionService e = new ExecutorCompletionService(Executors.newCachedThreadPoolExecutor());

Set<Future<Result>> futures = new HashSet<>();

// submit your tasks:
futures.add(e.submit(taskA));
futures.add(e.submit(taskB));
futures.add(e.submit(taskC));

// now call take() on the executor completion service,
// which will block the calling thread until the first task has completed
// either succesfully or abruptly (with an exception)
Future<Result> f = e.take();

在此之后,当您调用 时f.get(),您将获得一个实例,Result或者它会抛出一个ExectutionException(包装执行抛出的异常)。任何一个都会立即发生(感谢执行者完成服务)。

然后您将做出相应的反应:如果f.get()抛出异常,f则从futures集合中删除,遍历集合的其他元素(即通过您提交的其他任务),以及.cancel()它们。Callables 必须被编码为可取消,否则调用将.cancel()什么也不做。

于 2011-08-21T16:29:45.800 回答
0

您可以将 A、B、C 作业包装在一个Runnable知道作业何时失败并且还知道控制线程的 a 中。当此包装器检测到作业失败(异常、运行时条件等)时,它将通知控制线程以采取进一步行动。

这样您就不必轮询线程,但您将等待来自包装错误检测器的信号。

于 2011-08-21T16:15:22.780 回答
0

您可以向作业添加回调,在线程失败的情况下调用该回调。然后回调将继续停止所有线程。

于 2011-08-21T16:16:48.010 回答