我接到一个来自用户的作业列表的调用说用户发布了3个作业A,B和C,它们都在自己的线程AT,BT和CT中开始执行,然后我开始监视这3个线程,如果其中一个失败的工作说B失败了,我需要发出A和C信号停止。当所有线程都停止返回时,如果所有线程都失败则返回true。
目前我有一个很大的while循环,它做了50ms的检查和睡眠,这有效,但我想知道我有一个更好的方法来做这个没有任何类型的睡眠,我试着睡觉0ms AFAIK这把我的线程到了cpu que的末尾,但它仍然使用了太多的CPU大约60%。
答案 0 :(得分: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()
他们。必须将Callable
编码为可取消,否则对.cancel()
的调用将无效。
答案 1 :(得分:0)
您可以将A,B,C作业包装在Runnable
中,该{{1}}知道作业失败的时间并且也知道控制线程。当这个包装器检测到作业失败时(异常,运行时条件和不是),它将通知控制线程以进一步操作。
这样您就不必轮询线程,但是您将等待来自包装器错误检测器的信号。
答案 2 :(得分:0)
您可以向作业添加回调,在线程失败的情况下调用该回调。然后回调将继续停止所有线程。