Reputation: 1445
I have n tasks T1, T2, ... , Tn. I am looking for convenience code to accomplish the following algorithm:
Execute these n tasks concurrently and if a task Tx has completed successfully, stop/don't execute all other tasks Ty where y > x.
Successfully here means finding a solution, not all tasks will find a solution.
Using ExecutorService.invokeAll isn't that good, because all threads are running until completion.
ExecutorService.invokeAny doesn't work because it isn't guarenteed that the task x which finished first is the smallest x.
Any idea?
Upvotes: 1
Views: 204
Reputation: 712
This should do the trick:
T invoke(List<Callable<T>> tasks) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(tasks.size());
List<Future<T>> futures = tasks.stream()
.map(executorService::submit)
.collect(toList());
T result = null;
for (Future<T> future : futures)
if (result == null)
try { result = future.get(); }
catch (ExecutionException e) { }
else
future.cancel(true);
return result;
}
Upvotes: 0
Reputation: 2058
You can use threads to execute those tasks, you will need to store those threads in a List then you can run all of them with a loop once a thread is finished (successfully) you will use the list of thread to stop the others
public class Task implements Runnable {
private MainThread mainThread;
@Override
public void run() {
while(true){
// do something
if(success) {
// may be it will be usefull if you inject the success thread in the stop process method (to know which thread has done the task)
mainThread.stopProcess(this);
break;
}
// this condition will stop the thread
if (Thread.currentThread().isInterrupted()) {
// cleanup and stop execution
// for example a break in a loop
break;
}
}
}
}
In your main thread class you will manage your threads (tasks)
public class MainThread {
public boolean stopProcess = false;
public List<Thread> processors;
// add constructor with some initialization logic for processors list, inject in each processor the main Thread class (this)
public void process(){
for(Thread process : processors){
process.start();
}
}
public synchronized stopProcess(Runnable task){
if(!stopProcess){
stopProcess = true;
for(Thread process : processors){
process.interrupt();
}
}
}
}
Upvotes: 0
Reputation: 84
You can invokeAll keep the references the the Futures you get back and cancel them whenever you want.
Upvotes: 1