Java Threads : Callable and Future

Introduction:

Whenever it comes to creating a thread in Java we think of Runnable interface. Runnable has a method run with no parameters and no return value. But in case we expect some value to be returned after completion of a thread, we have to look for some workarounds. Callable is an interface introduced in Java 5 to take care of this specific requirement. Callable is similar to Runnable, but it returns a value.  A Future interface holds the result of asynchronous computation and it is used in conjunction with Callable. FutureTask is a wrapper class which implements both Future and Runnable interfaces and it provides a convenient way to convert a Callable into both a Future and a Runnable.

You can refer the online documentation of Java SE 5 to know more about Callable, Future and FutureTask.

Let us see a simple example demonstrating the use of Callable:

Objective:

To demonstrate how to use Callable and Future.

Explanation:

Create a StringGenerator thread which is supposed to return a random string to the caller. Create a StringGeneratorTest class which spawns ten StringGenerator thread and displays the concatenation of the string returned from all the threads.

The Code:

The StringGenerator Class:

package com.technicalmusings.samples.thread;

import java.util.concurrent.Callable;
import static java.lang.Math.random;

public class StringGenerator implements Callable<String> {

	public String call() throws Exception {
		String [] allStrings =
                {"Apple", "Ball", "Cat", "Dog", "Elephant",
                "Flower", "Grape", "Horse", "Ink","Joker"};
		int index = (int)(random()*100)/10;

		//Let's wait for sometime
		Thread.sleep(1000);
		return allStrings[index];
	}
}

The StringGeneratorTest class:

package com.technicalmusings.samples.thread;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class StringGeneratorTest {

	public static void main(String[] args) {

		//Create an array to store the future objects.
		ArrayList<Future<String>> results = new ArrayList<Future<String>>();
		for (int i=0; i<10; i++){
			//Create the instance of the Callable task
                        Callable<String> stringGenerator = new StringGenerator();

			//create the object of FutureTask
			FutureTask<String> task =
                                new FutureTask<String>(stringGenerator);

			//Add to the list
			results.add(task);

			//Create a thread object using the task object created
			Thread t = new Thread(task);

			//Start the thread as usual
			t.start();

		}

		//Compute the results now.
		StringBuilder resultStr = new StringBuilder();

		long start = System.currentTimeMillis();

		for(Future<String> result: results){
			try {
				//The blocking get call
				resultStr.append(result.get());
				resultStr.append(" ");

			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}

		long end = System.currentTimeMillis();

		System.out.println("The returned string is:\n"+resultStr);
		System.out.println("Execution time:"+(end - start));
	}
}

Output:

The returned string is:
Dog Dog Joker Elephant Flower Ball Grape Elephant Elephant Horse
Execution time:1014

The Executors class is also worth looking at as it contains utility methods to convert from other common forms to Callable.

Enjoy Learning,

Kamlesh

Advertisements