Neat Java 8 features - Concurrency API

This, the last of three posts is about the Java Concurrency API

Previous posts:

Concurrency API

The Concurrency API has been around for longer, but got some extra features with Java 8.

If you want to run tasks in parallel, wrap them either in a ‘Runnable’ (no return value) or a ‘Callable’ (has a return value). Submit these tasks to an ExecutorService and check the returned ‘Futures’ for completion, respectively get the results from them.

Here’s an example:

ExecutorService es = Executors.newWorkStealingPool();
List<Future<String>> futures = new ArrayList<Future<String>>();
for (int i=0; i<10; i++) {
    Callable<String> task = () -> {
    TimeUnit.SECONDS.sleep(1);
    return "This callable was executed by "
        + Thread.currentThread().getName();
    };
    futures.add(es.submit(task));
}
        
while(!futures.stream().allMatch(f -> f.isDone())) {
    TimeUnit.MILLISECONDS.sleep(100);
}
        
futures.stream().forEach(f ->  { 
    try {
        System.out.println(f.get());
     } catch (Exception e) {
         e.printStackTrace();
     }
});

Here’s another example using a CompletionService. With the CompletionService you don’t have to loop over the Futures and check if they are ready, you can simple take the next one which is ready from the service.

Random random = new Random();
        
CompletionService<String> cs = new ExecutorCompletionService<String>(Executors.newWorkStealingPool());
        
for (int i=0; i<10; i++) {
    Callable<String> task = () -> {
    // wait for 1 to 10 sec
    TimeUnit.SECONDS.sleep(random.nextInt(10)+1);
    return "This callable was executed by "
        + Thread.currentThread().getName();
    };
    cs.submit(task);
}

int completed = 0;
while (completed < 10) {
    // take the next one which is ready
    Future<String> fut = cs.take();
    System.out.println("Another one completed: "+fut.get());
    completed++;
}