简体   繁体   English

轮询多个线程和CPU使用率

[英]Polling Multiple Threads and CPU Usage

I have a call that receives a list of jobs from the user say user posted 3 jobs A, B and C, they all start execution in their own threads AT,BT and CT, then I start monitoring these 3 threads, if one of the jobs fail say B failed, I need to signal A and C to stop. 我有一个电话从用户那里收到一份工作清单,说用户发布了3个工作A,B和C,它们都开始在自己的线程AT,BT和CT中执行,然后我开始监视这3个线程,如果其中一个作业失败,说B失败,我需要向A和C发出信号才能停止。 When all threads stopped return, when all succeeds true if one fails false. 当所有线程都停止返回时,如果所有线程都失败,则返回true。

Currently I have a one big while loop that does the checking and sleeping for 50ms, Which works but I was wondering I there was a better way to do this without any sort of sleep, I tried sleeping 0ms AFAIK this puts my thread to the end of the cpu que but it still utilized way too much cpu around 60%. 目前,我有一个大的while循环,它可以进行50ms的检查和睡眠,这是可行的,但是我想知道有没有更好的方法可以做到这一点,而无需进行任何睡眠,我尝试了睡眠0ms AFAIK,这使我的线程结束了cpu que,但仍使用了过多的cpu约60%。

This sounds like a use case for ExecutorCompletionService 这听起来像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();

After this, when you call f.get() , you will either get an instance of Result or it will throw an ExectutionException (wrapping the exception thrown by the execution). 此后,当您调用f.get() ,您将获得Result的实例,或者将抛出ExectutionException (包装由执行抛出的异常)。 Either one will happen immediately (thanks to the executor completion service). 任何一种都会立即发生(由于执行程序完成服务)。

Then you will react accordingly: if f.get() throws an exception, remove f from the futures set, iterate through the other elements of the set (that is, through the other tasks you submitted), and .cancel() them. 然后,您将做出相应的反应:如果f.get()引发异常,则将ffutures集合中移除,遍历集合的其他元素(即,通过提交的其他任务),然后.cancel()它们进行.cancel() The Callable s must be coded to be cancelable, otherwise the call to .cancel() will do nothing. 必须将Callable编码为可取消的,否则对.cancel()的调用将.cancel()

You can wrap the A, B, C jobs in a Runnable that knows when a job failed and also knows about the controlling thread. 您可以将A,B,C作业包装在一个Runnable ,该Runnable知道作业何时失败,还知道控制线程。 When this wrapper it detects that job failed (exception, runtime conditions and what not) it will notify the controlling thread for further action. 当该包装器检测到作业失败(异常,运行时条件以及其他原因)时,它将通知控制线程采取进一步的措施。

That way you will not have to poll the threads but you will wait on a signal from the wrapper error detector. 这样,您将不必轮询线程,但是将等待来自包装器错误检测器的信号。

You can add a callback to the jobs, which is invoked in the case that the thread fails. 您可以将回调添加到作业,在线程失败的情况下调用该回调。 The callback then would proceed to stop all threads. 然后,回调将继续停止所有线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM