Executor, ExecutorService, Executor - 1

"Hi, Amigo!"

"Nothing is perfect when it is first created. The same is true of threads. In time, Java's creators became convinced of the shortcomings of the Runnable interface. It didn't support throwing exceptions and didn't make it possible to find out the result of executing tasks…"

"The Runnable interface is more suitable for large independent tasks than for small subtasks that you want to run a dozen at a time, and then collect their results."

"That's why the Callable interface was invented. It's much better suited for parallel execution of small tasks than Runnable and Thread, in part because it's a generic interface."

"Here's a typical implementation of the interface:"

Example
class ReverseString implements Callable<String>
{
 String str;

 ReverseString(String str)
 {
  this.str = str;
 }

 public String call() throws Exception
 {
  StringBuilder builder = new StringBuilder(str);
  builder.reverse();
  return builder.toString();
 }
}

"Unlike Runnable, here we need to override the call method, which returns a result of the type specified by the type argument. This approach is much more convenient than the Runnable interface's run method, which returns void. Sometimes developers had to come up with various workarounds to get a thread's result."

"I see."

"And now look at how Callable can work together with ThreadPoolExecutor:

"First, the ThreadPoolExecutor class's submit method returns a parameterized Future object. You can use this object to find out whether a task if finished and to get the result."

"Here's how it works:"

Example
// 1. Create a ThreadPoolExecutor
ExecutorService service = Executors.newFixedThreadPool(5);

// 2. Add a task to it
Future<String> task = service.submit(new ReverseString("Amigo"));

// 3. Wait until the task is done
while(!task.isDone())
{
 Thread.sleep(1);
}

// 4. Try to get the result
//We will get either the result, or an exception if one occurred while the task was being executed
try
{
 System.out.println("Full string : " + task.get());
}
catch (Exception ie)
{
 ie.printStackTrace(System.err);
}
  
// 5. Stop the ThreadPool.
service.shutdown();

"Far out! I especially like the Future class. What methods does it have?"

"Here are the most interesting:"

Method Description
boolean cancel(boolean mayInterrupt);
Stops the task.
boolean isCancelled();
Returns true if the task was stopped.
boolean isDone();
Returns true if task is done being executed.
V get() throws InterruptedException, ExecutionException;
Returns the result of the call method or throws an exception if one occurred.

"Cool! So you can also stop tasks."

"Don't rely on this too much—not every thread can stop. But if a task is still in the queue, then this will work fine."

"I like this approach. It's much more convenient than creating threads yourself and then trying to pull a result out of them."

"Great. That's where we'll end today."