Thursday, September 2, 2010

Java Threads : Using Callable

                      Threads , the first thing which comes to mind is the Runnable Interface. 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.

Lets see an example which implements the same:


Make a StringGenerator Class:

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

public class StringGenerator implements Callable {

    public String call() throws Exception {
        String [] allStrings =
                {"Wine", "Movies", "Party", "Books", "Shopping",
                "Flowers", "Food", "Music", "Cars","Jewelery"};
        int index = (int)(random()*100)/10;

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


Next make a StringGeneratorTest class:

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> results = new ArrayList>();
        for (int i=0; i<10; i++){
            //Create the instance of the Callable task
                        Callable stringGenerator = new StringGenerator();

            //create the object of FutureTask
            FutureTask task =
                                new FutureTask(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 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:
Shopping Party Party Flowers Books Wine Wine Flowers Music Cars
Execution time:1002

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.


Hope this helped !!! Cheers !! :-)

References: