I know Callable allows to return a value or checked exception whereas Runnable doesn't. This question is not about the difference between the two interfaces but about the sequential returns of the values in following code.
Please have a look at the following code segment.
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> futureList = new ArrayList<Future<String>>();
for (int i=0;i<10;i++) {
Runner runner = new Runner(i);
Future<String> future = executorService.submit(runner);
futureList.add(future);
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
for (Future<String> integerFuture : futureList) {
System.out.println("Returned value is : " + integerFuture.get());
}
The Runner class for this code is provided below.
public class Runner implements Callable<String> {
private int id;
public Runner(Integer id) {
this.id = id;
}
@Override
public String call() throws Exception {
Random randomWait = new Random();
Thread.sleep(randomWait.nextInt(5)*1000);
Random random = new Random();
int randomInt = random.nextInt(100);
return id + " - " + randomInt;
}
}
The above code always provides a sequential response despite the fact that the threads executing them may sleep different seconds.
Returned value is : 0 - 19
Returned value is : 1 - 88
Returned value is : 2 - 99
........
Returned value is : 9 - 42
But by comparison the following code segment provides more meaningful response, as the threads sleeps different time periods.
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i=0;i<10;i++) {
Runner runner = new Runner(i);
executorService.submit(runner);
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
The runner class for about segment is given below. public class Runner implements Runnable {
private int id;
public Runner(Integer id) {
this.id = id;
}
@Override
public void run() {
Random randomWait = new Random();
try {
Thread.sleep(randomWait.nextInt(5)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Runner : " + id + " Finished.");
}
}
As expected the response of this thread was non sequential.
Runner : 5 Finished.
Runner : 9 Finished.
Runner : 1 Finished.
Runner : 3 Finished.
........
So my question is why does the fist code segment with futures and callable response is always sequential ? It seems to me that the main thread waits till end end of executing all the threads and provides a sequential output. But there is nothing about it is mentioned in the javadoc. If the response was something like second one I could have understood it.
So my question is why does the fist code segment with futures and callable response is always sequential?
Because you're specifically asking for the result of the Futures
in the order in which they were submitted:
for (Future<String> integerFuture : futureList) {
System.out.println("Returned value is : " + integerFuture.get());
Here, Future.get()
will block until the call has completed - and your list is constructed by submitting callables; futureList.get(0)
is always going to be the future related to the first callable submitted, regardless of whether it's the first one to complete.
See more on this question at Stackoverflow