Normally when we work with threads and runnable does not return a processed product, for that reason we either need to have our own implementations using observer pattern or Callable interface provided default by Java
Even Callable interface has been designed by using observer patter. Observer pattern is simply to notify other concrete classes when one achieves a task. The below example is not a clear example but sufficient to apprehend the whole deal
App.java
package com.tugrulaslan.concurrent; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; /** * Created by Tugrul on 9/8/2015. */ public class App { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); //We are here to collect the product of the threads using future List<Future<String>> product = new ArrayList<Future<String>>(); //work for 10 times for (int i = 0; i < 10; i++) { Callable<String> callable = new CustomCallable(String.valueOf(System.currentTimeMillis())); Future<String> submittedTask = executorService.submit(callable); product.add(submittedTask); } //to fetch the result for(Future<String> obj : product){ try { System.out.println(obj.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } }
CustomCallable.java
package com.tugrulaslan.concurrent; import java.util.concurrent.Callable; /** * Created by Tugrul on 9/8/2015. */ public class CustomCallable implements Callable<String> { String message; public CustomCallable(String message) { this.message = message; } public CustomCallable() { } @Override public String call() throws Exception { Thread.sleep(1000); return new StringBuilder(message).reverse().toString(); } }