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开发者_JS百科 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. When all threads stopped return, when all succeeds true if one fails false.
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%.
This sounds like a use case for 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). 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. The Callable
s must be coded to be cancelable, otherwise the call to .cancel()
will do nothing.
You can wrap the A, B, C jobs in a Runnable
that knows when a job failed and also knows about the controlling thread. 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.
精彩评论