I'm well aware that this might be considered a duplicate, however I ran through many answers considering my problem here I can't come up with a solution.
I synchronized my runnable with an object shared by multiple threads and explicitly synchronized the method I am using inside, but the outcome of the program is always 3000.
I tried locking the Counter class but it won't change a thing.
Could anyone explain me why none of my actions work in this particular example?
public static void zad3() {
var counter = new Counter();
var toRun = new Runnable() {
#Override
public void run() {
synchronized (counter) {
for (var i = 0; i < 1000; i++) {
counter.add(1);
}
}
}
};
var t1 = new Thread(toRun);
var t2 = new Thread(toRun);
var t3 = new Thread(toRun);
t1.start();
t2.start();
t3.start();
try {
t1.join();
t2.join();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("counter = " + counter.getCount());
}
public class Counter {
protected long count_ = 0;
public synchronized void add(long value) {
count_ += value;
}
public long getCount() {
return count_;
}
}
edit:
As suggested the problem was in the loop being constantly ran a 1000 times by each of the threads.
My solution:
var toRun = new Runnable() {
#Override
public void run() {
synchronized (counter) {
for (var i = counter.getCount(); i < 1000; i++) {
counter.add(1);
}
}
}
};
Well you have synchronized the complete for loop around the "counter" variable which means that each thread will run tthe block once. 3 X 1000 = 3000
this block will be executed once per thread
for (var i = 0; i < 1000; i++) {
counter.add(1);
}
UPDATE: judging from your comments that you want interrupt on 1000 example code can be:
t1.start();
t2.start();
t3.start();
while(counter.getValue()<1000) {
Thread.sleep(20)
}
Annother suggestion:
public class Incremetor extends Runnable {
Counter counter;
public Incremetor(Counter counter) {
this.counter = counter;
}
public void run() {
counter.increment();
}
}
ExecutorService executorService = Executors.newFixedThreadPool(8); // this mean 8 threads in total to do your runnables.
for (int i=0;i<1000;++i) {
executorService.submit(new Incrementor(counter));
}
So the problem is that you let each thread attempt 1000 increments, so you'll need something like this instead:
while (counter.getCount() < 1000) {
counter.add(1);
}
The solution you have provided may give you the correct result, but you're actually only incrementing the counter from 1 thread. When you make a synchronized block with synchronized(object) { }, all threads will attempt to get the lock for this block, but only one will. That means in your solution, that the first thread which gets the lock, will do all 1000 increments. When the thread releases the lock and lets the others get it, the work is already done. A solution that actually distributes the increments amongst the 3 threads, should therefore not synchronize the entire for-loop.
If you run the while-loop I suggested, you will get a lot closer to 1000, but it may actually be more than 1000. Remember to run your program 10 times or set up a test-function which runs it 100 times and reports back. The problem, is that from the point of reading counter.getCount(), the value may already have changed by another thread. To reliably always get 1000, you could ensure exclusive rights to both reading and writing to the counter:
while (true) {
synchronized (counter) {
if (counter.getCount() < 1000) {
counter.add(1);
} else {
break;
}
}
}
Notice that incrementing one variable like this, is slow. You're only doing 1000, but try with one billion. In fact, the 3-threaded version takes (on my PC) 1m17s, whereas a simple sequential loop takes ~1.2 seconds. You can solve this by splitting the workload amongst the threads and letting them work on a local counter with exclusive rights and then finally add the results.
Related
I am creating program to run a logic in parallel with help of thread. The logic has to be done in a loop of a list and that list may contain 1000 rows to process , so i started each thread in a loop and once thread size reaches 5, i will call thread.join for all the 5 started thread.
So i think that this will start the 2nd set of 5 threads only after the first set of 5 threads are completed? is my understanding correct? i am kind of new to threads.
So my need is to start the 6th thread when any one of the previous set of 5 threads in completed. or start 6th and 7th when any 2 in the previous set of threads are completed.
My code
public static void executeTest(){
for (int i = 0; i < rows1; i++) {
RunnableInterface task = new New RunnableInterface(params);
Thread thread = new Thread(task);
thread.start();
threads.add(thread);
if ((threads.size() % 5 == 0) || ((i == rows1-1) && (threads.size() < 5))) {
waitForThreads(threads);
}
}
}
private static void waitForThreads(List<Thread> threads) {
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
threads.clear();
}
What kind of modification do i need to do to achieve above mentioned results
You can use an ExecutorService with unbounded input queue and fixed number of threads like this:
ExecutorService exec = Executors.newFixedThreadPool(5);
// As many times as needed:
for(int i = 0; i< 100_000; i++) {
Runnable myrunnable = () -> {}; // new RunnableInterface(params)
exec.submit(myrunnable);
}
exec.shutdown();
exec.awaitTermination(1, TimeUnit.DAYS);
In JDK19 the executor service is AutoClosable, so you can simplify to:
try (ExecutorService exec = Executors.newFixedThreadPool(5)) {
...
}
When in doubt, break it down into smaller, simpler functions:
public static void executeTest(){
for (int i = 0; i < rows1; i++) {
startFiveThreads(i);
awaitFiveThreads(i);
}
}
private static void startFiveThreads(int i) {
...
}
private static void awaitFiveThreads(int i) {
...
}
But seriously? I'm giving you a literal answer to your question—a better way to implement your solution. #DuncG showed you a better solution for your problem. Definitely go with what DuncG said, but maybe remember what I said for next time you are trying to implement some tricky/complex algorithm.
The following code is shows how no race condition in thread works, but I don't get the difference between with the synchronized and without it. I thought the static variable counter will be added to 20000 anyway but it turned out that without synchronized counter would be less than 20000. Can you please explain how threads work in this case? Also, in Java, are threads are actually not running "concurrently", instead are they taking turns to run for a while?
public class NoRaceCondition implements Runnable {
private static int counter = 0;
private static Object gateKeeper = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new NoRaceCondition());
Thread t2 = new Thread(new NoRaceCondition());
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.printf("counter = %d\n", counter);
}
public void run() {
synchronized (gateKeeper) {
for (int i = 0; i < 10000; i++) {
{
counter++;
}
}
}
}
}
You can think of count++ as 3 separate steps.
read the value of count
increment the value
override count with the new incremented value
When multiple thread execute the above steps concurrently, race conditions may occur. 1 example of race condition is
Let count = 1
Let there be 2 threads named A and B
Thread A reads the value of count and get 1
Thread B reads the value of count and get 1
Thread A increments its value and get 2
Thread B increments its value and get 2
Thread A writes the value to count
count is now 2
Thread B writes the value to count
count is now 2 again when it's expected to be 3 after 2 increments
public class TestThread2 {
static int count = 0;
public static void main(String[] args) {
Thread t = new Thread(new Runnable(){
public void run()
{
for (int i=1; i<=100000; i++) {
count++;
}
}
});
Thread t1 = new Thread(new Runnable(){
public void run()
{
for (int i=1; i<=100000; i++) {
count++;
}
}
});
t.start();
t1.start();
try{
t.join();
t1.join();
}
catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(count);
}
}
The above code prints various values of count such as 131938, 127518 etc. But I think it should always print 20000 as after join() is called, main thread cannot move to next statement until current thread dies. I know I'm missing a basic concept here, but I'm not able to figure it out so please help.
i++ isn't atomic. It's effectively:
int j = i;
i = j + 1;
If two threads are trying to do this at the same time, the reads and writes from different threads could interleave, meaning that the value isn't strictly incrementing in each thread.
Additionally, there is no guarantee that the increased value from one thread is visible to the other thread.
Instead of using int, use AtomicInteger, and addAndGet. AtomicInteger guarantees both the atomicity of the incrementation and the visibility of the value between threads.
static AtomicInteger count = new AtomicInteger();
// In the thread:
count.incrementAndGet();
Note that something very similar to your example is described in the Oracle Java Tutorial.
You are not synchronizing the variables. Instead of static int count, use an AtomicInteger.
Yes main thread blocks on join(). But the main thread does not write to the variable count, so it does not matter what main thread is doing. You have 2 threads, t and t1, which read and write the same variable count without any synchronization, and indeed it causes unstable results.
I am trying to synchronize three threads to print 012012012012.... but it is not working correctly. Each thread is assigned a number which it prints when it receives a signal from main thread. There is something wrong with the following program which I am not able to catch.
public class Application {
public static void main(String[] args) {
int totalThreads = 3;
Thread[] threads = new Thread[totalThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new MyThread(i);
threads[i].start();
}
int threadIndex = 0;
while (true) {
synchronized(threads[threadIndex]) {
threads[threadIndex].notify();
}
threadIndex++;
if (threadIndex == totalThreads) {
threadIndex = 0;
}
}
}
}
class MyThread extends Thread {
private int i;
public MyThread(int i) {
this.i = i;
}
#Override
public void run() {
while (true) {
synchronized(this) {
waitForSignal();
System.out.println(i);
}
}
}
private void waitForSignal() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You need more coordination. the notify call does not immediately wake up the thread and force it to proceed. Instead, think of notify as sending an email to the thread to let it know that it can proceed. Imagine if you wanted your 3 friends to call you in order. You sent friend 1 an email to call you, waited one second, sent an email to friend 2, waited a second, and sent an email to friend 3. do you think you'd get called in that exact order?
one way to add more coordination would be to have some shared state which indicates whose turn it is. if all your friends could see your house, you could put a number on the outside of the house indicating whose turn it was to call. each friend would wait until they saw their number, and then call.
Here's your problem:
int threadIndex = 0;
while (true) {
synchronized(threads[threadIndex]) {
threads[threadIndex].notify();
}
threadIndex++;
if (threadIndex == totalThreads) {
threadIndex = 0;
}
}
The main thread notifies all threads in the right order. However, your threads are working independently. They may or may not get scheduled at a specific point in time. So the end result may be, that thread 2 is reaching the wait/print lock before thread 1 before thread 0. The final order is not determined by you sending the notifications, but (in essence) by the scheduler.
The solution is to change it this way:
the main thread notifies exactly one thread: thread 0
every thread does his work and when done, notifies the next thread in line
obviously the last thread has to notify thread 0 again.
Another possible solution: In the main thread, you can wait immediately after having notified a thread (in the same synchronized block), like this:
synchronized (threads[threadIndex])
{
threads[threadIndex].notify();
threads[threadIndex].wait(); // try/catch here
}
And in the run method of the thread, you can use notifyAll to wake up the main thread after the thread finished its work:
synchronized (this)
{
waitForSignal();
System.out.println(i);
notifyAll();
}
More sophisticated solutions would involve classes from the java.util.concurrent.locks package.
package threads;
import java.util.concurrent.Semaphore;
public class ZeroEvenOddPrinter {
class Runner extends Thread{
Semaphore prev;
Semaphore next;
int num = 0;
public Runner(Semaphore prev,Semaphore next,int num){
this.prev = prev;
this.next = next;
this.num = num;
}
#Override
public void run(){
while (true) {
try {
Thread.sleep(100);
prev.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (num == 0)
System.out.println(0);
else {
System.out.println(num);
num = num + 2;
}
next.release();
}
}
}
static public void main(String args[]) throws InterruptedException{
Semaphore sem1 = new Semaphore(1);
Semaphore sem2 = new Semaphore(1);
Semaphore sem3 = new Semaphore(1);
ZeroEvenOddPrinter zeo = new ZeroEvenOddPrinter();
Runner t1 = zeo.new Runner(sem1,sem2,0);
Runner t2 = zeo.new Runner(sem2,sem3,1);
Runner t3 = zeo.new Runner(sem3,sem1,2);
sem1.acquire();
sem2.acquire();
sem3.acquire();
t1.start();
t2.start();
t3.start();
sem1.release();
}
}
Here i am using semaphores as triggers for all the three threads. Initially all threads will be blocked on sem1,sem2,sem3. Then i will release the sem1 and first thread will execute then it will release the second thread and so on... The best part is you extend this logic to n number of threads. Good Luck!!!
What is a way to simply wait for all threaded process to finish? For example, let's say I have:
public class DoSomethingInAThread implements Runnable{
public static void main(String[] args) {
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread());
t.start();
}
// wait for all threads' run() methods to complete before continuing
}
public void run() {
// do something here
}
}
How do I alter this so the main() method pauses at the comment until all threads' run() methods exit? Thanks!
You put all threads in an array, start them all, and then have a loop
for(i = 0; i < threads.length; i++)
threads[i].join();
Each join will block until the respective thread has completed. Threads may complete in a different order than you joining them, but that's not a problem: when the loop exits, all threads are completed.
One way would be to make a List of Threads, create and launch each thread, while adding it to the list. Once everything is launched, loop back through the list and call join() on each one. It doesn't matter what order the threads finish executing in, all you need to know is that by the time that second loop finishes executing, every thread will have completed.
A better approach is to use an ExecutorService and its associated methods:
List<Callable> callables = ... // assemble list of Callables here
// Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
// bother saving them
Using an ExecutorService (and all of the new stuff from Java 5's concurrency utilities) is incredibly flexible, and the above example barely even scratches the surface.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class DoSomethingInAThread implements Runnable
{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
//limit the number of actual threads
int poolSize = 10;
ExecutorService service = Executors.newFixedThreadPool(poolSize);
List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
for (int n = 0; n < 1000; n++)
{
Future f = service.submit(new DoSomethingInAThread());
futures.add(f);
}
// wait for all tasks to complete before continuing
for (Future<Runnable> f : futures)
{
f.get();
}
//shut down the executor service so that this thread can exit
service.shutdownNow();
}
public void run()
{
// do something here
}
}
instead of join(), which is an old API, you can use CountDownLatch. I have modified your code as below to fulfil your requirement.
import java.util.concurrent.*;
class DoSomethingInAThread implements Runnable{
CountDownLatch latch;
public DoSomethingInAThread(CountDownLatch latch){
this.latch = latch;
}
public void run() {
try{
System.out.println("Do some thing");
latch.countDown();
}catch(Exception err){
err.printStackTrace();
}
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
try{
CountDownLatch latch = new CountDownLatch(1000);
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread(latch));
t.start();
}
latch.await();
System.out.println("In Main thread after completion of 1000 threads");
}catch(Exception err){
err.printStackTrace();
}
}
}
Explanation:
CountDownLatch has been initialized with given count 1000 as per your requirement.
Each worker thread DoSomethingInAThread will decrement the CountDownLatch, which has been passed in constructor.
Main thread CountDownLatchDemo await() till the count has become zero. Once the count has become zero, you will get below line in output.
In Main thread after completion of 1000 threads
More info from oracle documentation page
public void await()
throws InterruptedException
Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted.
Refer to related SE question for other options:
wait until all threads finish their work in java
Avoid the Thread class altogether and instead use the higher abstractions provided in java.util.concurrent
The ExecutorService class provides the method invokeAll that seems to do just what you want.
Consider using java.util.concurrent.CountDownLatch. Examples in javadocs
Depending on your needs, you may also want to check out the classes CountDownLatch and CyclicBarrier in the java.util.concurrent package. They can be useful if you want your threads to wait for each other, or if you want more fine-grained control over the way your threads execute (e.g., waiting in their internal execution for another thread to set some state). You could also use a CountDownLatch to signal all of your threads to start at the same time, instead of starting them one by one as you iterate through your loop. The standard API docs have an example of this, plus using another CountDownLatch to wait for all threads to complete their execution.
As Martin K suggested java.util.concurrent.CountDownLatch seems to be a better solution for this. Just adding an example for the same
public class CountDownLatchDemo
{
public static void main (String[] args)
{
int noOfThreads = 5;
// Declare the count down latch based on the number of threads you need
// to wait on
final CountDownLatch executionCompleted = new CountDownLatch(noOfThreads);
for (int i = 0; i < noOfThreads; i++)
{
new Thread()
{
#Override
public void run ()
{
System.out.println("I am executed by :" + Thread.currentThread().getName());
try
{
// Dummy sleep
Thread.sleep(3000);
// One thread has completed its job
executionCompleted.countDown();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
try
{
// Wait till the count down latch opens.In the given case till five
// times countDown method is invoked
executionCompleted.await();
System.out.println("All over");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
If you make a list of the threads, you can loop through them and .join() against each, and your loop will finish when all the threads have. I haven't tried it though.
http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join()
Create the thread object inside the first for loop.
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
// some code to run in parallel
}
});
threads[i].start();
}
And then so what everyone here is saying.
for(i = 0; i < threads.length; i++)
threads[i].join();
You can do it with the Object "ThreadGroup" and its parameter activeCount:
As an alternative to CountDownLatch you can also use CyclicBarrier e.g.
public class ThreadWaitEx {
static CyclicBarrier barrier = new CyclicBarrier(100, new Runnable(){
public void run(){
System.out.println("clean up job after all tasks are done.");
}
});
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new MyCallable(barrier));
t.start();
}
}
}
class MyCallable implements Runnable{
private CyclicBarrier b = null;
public MyCallable(CyclicBarrier b){
this.b = b;
}
#Override
public void run(){
try {
//do something
System.out.println(Thread.currentThread().getName()+" is waiting for barrier after completing his job.");
b.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
To use CyclicBarrier in this case barrier.await() should be the last statement i.e. when your thread is done with its job. CyclicBarrier can be used again with its reset() method. To quote javadocs:
A CyclicBarrier supports an optional Runnable command that is run once per barrier point, after the last thread in the party arrives, but before any threads are released. This barrier action is useful for updating shared-state before any of the parties continue.
The join() was not helpful to me. see this sample in Kotlin:
val timeInMillis = System.currentTimeMillis()
ThreadUtils.startNewThread(Runnable {
for (i in 1..5) {
val t = Thread(Runnable {
Thread.sleep(50)
var a = i
kotlin.io.println(Thread.currentThread().name + "|" + "a=$a")
Thread.sleep(200)
for (j in 1..5) {
a *= j
Thread.sleep(100)
kotlin.io.println(Thread.currentThread().name + "|" + "$a*$j=$a")
}
kotlin.io.println(Thread.currentThread().name + "|TaskDurationInMillis = " + (System.currentTimeMillis() - timeInMillis))
})
t.start()
}
})
The result:
Thread-5|a=5
Thread-1|a=1
Thread-3|a=3
Thread-2|a=2
Thread-4|a=4
Thread-2|2*1=2
Thread-3|3*1=3
Thread-1|1*1=1
Thread-5|5*1=5
Thread-4|4*1=4
Thread-1|2*2=2
Thread-5|10*2=10
Thread-3|6*2=6
Thread-4|8*2=8
Thread-2|4*2=4
Thread-3|18*3=18
Thread-1|6*3=6
Thread-5|30*3=30
Thread-2|12*3=12
Thread-4|24*3=24
Thread-4|96*4=96
Thread-2|48*4=48
Thread-5|120*4=120
Thread-1|24*4=24
Thread-3|72*4=72
Thread-5|600*5=600
Thread-4|480*5=480
Thread-3|360*5=360
Thread-1|120*5=120
Thread-2|240*5=240
Thread-1|TaskDurationInMillis = 765
Thread-3|TaskDurationInMillis = 765
Thread-4|TaskDurationInMillis = 765
Thread-5|TaskDurationInMillis = 765
Thread-2|TaskDurationInMillis = 765
Now let me use the join() for threads:
val timeInMillis = System.currentTimeMillis()
ThreadUtils.startNewThread(Runnable {
for (i in 1..5) {
val t = Thread(Runnable {
Thread.sleep(50)
var a = i
kotlin.io.println(Thread.currentThread().name + "|" + "a=$a")
Thread.sleep(200)
for (j in 1..5) {
a *= j
Thread.sleep(100)
kotlin.io.println(Thread.currentThread().name + "|" + "$a*$j=$a")
}
kotlin.io.println(Thread.currentThread().name + "|TaskDurationInMillis = " + (System.currentTimeMillis() - timeInMillis))
})
t.start()
t.join()
}
})
And the result:
Thread-1|a=1
Thread-1|1*1=1
Thread-1|2*2=2
Thread-1|6*3=6
Thread-1|24*4=24
Thread-1|120*5=120
Thread-1|TaskDurationInMillis = 815
Thread-2|a=2
Thread-2|2*1=2
Thread-2|4*2=4
Thread-2|12*3=12
Thread-2|48*4=48
Thread-2|240*5=240
Thread-2|TaskDurationInMillis = 1568
Thread-3|a=3
Thread-3|3*1=3
Thread-3|6*2=6
Thread-3|18*3=18
Thread-3|72*4=72
Thread-3|360*5=360
Thread-3|TaskDurationInMillis = 2323
Thread-4|a=4
Thread-4|4*1=4
Thread-4|8*2=8
Thread-4|24*3=24
Thread-4|96*4=96
Thread-4|480*5=480
Thread-4|TaskDurationInMillis = 3078
Thread-5|a=5
Thread-5|5*1=5
Thread-5|10*2=10
Thread-5|30*3=30
Thread-5|120*4=120
Thread-5|600*5=600
Thread-5|TaskDurationInMillis = 3833
As it's clear when we use the join:
The threads are running sequentially.
The first sample takes 765 Milliseconds while the second sample takes 3833 Milliseconds.
Our solution to prevent blocking other threads was creating an ArrayList:
val threads = ArrayList<Thread>()
Now when we want to start a new thread we most add it to the ArrayList:
addThreadToArray(
ThreadUtils.startNewThread(Runnable {
...
})
)
The addThreadToArray function:
#Synchronized
fun addThreadToArray(th: Thread) {
threads.add(th)
}
The startNewThread funstion:
fun startNewThread(runnable: Runnable) : Thread {
val th = Thread(runnable)
th.isDaemon = false
th.priority = Thread.MAX_PRIORITY
th.start()
return th
}
Check the completion of the threads as below everywhere it's needed:
val notAliveThreads = ArrayList<Thread>()
for (t in threads)
if (!t.isAlive)
notAliveThreads.add(t)
threads.removeAll(notAliveThreads)
if (threads.size == 0){
// The size is 0 -> there is no alive threads.
}
The problem with:
for(i = 0; i < threads.length; i++)
threads[i].join();
...is, that threads[i + 1] never can join before threads[i].
Except the "latch"ed ones, all solutions have this lack.
No one here (yet) mentioned ExecutorCompletionService, it allows to join threads/tasks according to their completion order:
public class ExecutorCompletionService<V>
extends Object
implements CompletionService<V>
A CompletionService that uses a supplied Executor to execute tasks. This class arranges that submitted tasks are, upon completion, placed on a queue accessible using take. The class is lightweight enough to be suitable for transient use when processing groups of tasks.
Usage Examples.
Suppose you have a set of solvers for a certain problem, each returning a value of some type Result, and would like to run them concurrently, processing the results of each of them that return a non-null value, in some method use(Result r). You could write this as:
void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException, ExecutionException {
CompletionService<Result> cs = new ExecutorCompletionService<>(e);
solvers.forEach(cs::submit);
for (int i = solvers.size(); i > 0; i--) {
Result r = cs.take().get();
if (r != null)
use(r);
}
}
Suppose instead that you would like to use the first non-null result of the set of tasks, ignoring any that encounter exceptions, and cancelling all other tasks when the first one is ready:
void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
CompletionService<Result> cs = new ExecutorCompletionService<>(e);
int n = solvers.size();
List<Future<Result>> futures = new ArrayList<>(n);
Result result = null;
try {
solvers.forEach(solver -> futures.add(cs.submit(solver)));
for (int i = n; i > 0; i--) {
try {
Result r = cs.take().get();
if (r != null) {
result = r;
break;
}
} catch (ExecutionException ignore) {}
}
} finally {
futures.forEach(future -> future.cancel(true));
}
if (result != null)
use(result);
}
Since: 1.5 (!)
Assuming use(r) (of Example 1) also asynchronous, we had a big advantage. #