Showing posts with label task. Show all posts
Showing posts with label task. Show all posts

Sunday, June 30, 2013

Callable and Future in Java

Runnable is default abstraction for creating a task in Java. It has a single method run() that accepts no arguments and returns no value, nor it can throw any checked exception. To overcome these limitations, Java 5 introduced a new task abstraction through Callable [javadoc ] interface.
public interface Callable<V>{
     V call() throws Exception;
}
Evident from the Callable interface shown above, call() method can return an Object, or more specifically any generic type. Like Runnable, Callable is also designed to be executed by threads. But you can't directly pass a Callable into Thread for execution. Check below snippet :

         Callable task = new Callable(){
  public Integer call(){
System.out.println("inside call method");
   return 1;
}
        };
Thread t = new Thread(task);    //doesn't compile

The last line in above code will not compile. It gives below compilation error message:  
"The constructor Thread(Callable) is undefined".
It tells Thread can't take a Callable argument.

Recall that Thread class implements Runnable interface, and it has been with Java since version 1.0, whereas Callable got added to the language in version 5.0 (or 1.5) only.

Running a Callable Task

Passing Callable into Thread for execution is out of question. Java SE 5 provides ExecutorService to execute the Callable object. The service accepts a Callable object.

        <T> Future<T> submit(Callable<T> task);

As above definition shows, submitting a Callable object to ExecutorService returns Future object. Future represents the life cycle of a task and is discussed below:

        Callable<List<T>> task = new Callable<List<T>>(){
               public List<T> call(){
                    List<T> results = new ArrayList<T>();
                   
                    //computation
                   
                    return results;
               }
        };

       ExecutorService es = Executors.newSingleThreadExecutor();

       Future<List<T>> future = es.submit(task);
       List<T> data = future.get();
       System.out.println("List Data :"+ data); 

The get() method of Future blocks, until the task is completed. This is equivalent to join() (i.e. t.join()) in normal thread case.

A closer look at Future

Future represents the life cycle of a task and provides methods to test whether the task has completed or been canceled, retrieve the result, and cancel the task. The behavior of get method depends on the state of the task (yet to start, completed, running). Get method returns immediately or throws Exception if the task has already completed. If the task is not completed then it blocks until the task completes. 
Future class methods
Straight from Java Doc :
Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the results of the computation.  The results can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was canceled. Once a computation has completed, the computation cannot be canceled. If you would use a Future for the sake of cancellability but not provide a usable result, you can declare the type of the form Future<?> and return null as a result of the underlying task.

----

post your comments/questions below !!!

Sunday, April 28, 2013

Latch API in Java : CountDownLatch

Literally, latch means a device for keeping a door or gate closed.  Its meaning is analogous to a gate in Java as well. So if latch (gate) is open, everyone can pass through it but when it's shut, no one is allowed to cross over. With this as background let's go in detail:

It's one of the advanced threading/concurrency concepts of Java. Java provides a Latch API named as  CountDownLatch which got introduced in Java 5 ( java.util.concurrent package). So now on; I will refer Latch and CountDownLatch interchangeably to refer to the same thing. Latch is a synchronizer that can delay the progress of threads until it reaches its terminal state. [A synchronizer is any object that coordinates the control flow of threads based on its state] So it is used to synchronize one or more tasks by forcing them to wait for the completion of a set of operation being performed by other tasks.

CountDownLatch in action

Let me start directly with a simple example to stress on the fundamentals of this API. Below sample program has two tasks (as taskone() and tasktwo()) represented as methods. And I want to make sure that taskone() should get completed before tasktwo(). 

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class CountDownLatchTest {
 static CountDownLatch latch;

 CountDownLatchTest(final int count) {
  latch = new CountDownLatch(count);
 }

 public void firstTask() {
  Runnable s1 = new Runnable() {
   public void run() {
    try {
         System.out.println("waiting....");
         TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
         e.printStackTrace();
    }
    // finish first activity before last line
    latch.countDown();
   }
  };
  Thread t = new Thread(s1);
  t.start();
 }

 public void secondTask() {
  Runnable s2 = new Runnable() {
   public void run() {
    try {
         System.out.println("wait....");
         latch.await();
         // perform task here
         System.out.println("after wait.... done");
    } catch (InterruptedException e1) {
         e1.printStackTrace();
    }
   }
  };
  Thread t = new Thread(s2);
  t.start();
 }

 public static void main(String[] args) throws InterruptedException {
  CountDownLatchTest cdlt = new CountDownLatchTest(1);
  cdlt.secondTask();
  TimeUnit.SECONDS.sleep(5);
  cdlt.firstTask();
 }
}

 Output:
 wait....
waiting....
after wait.... done

Above example shows CountDownLatch attribute getting initialized to a value of 1 through constructor. Two tasks in above example are synchronized though CountDownLatch. Task2 i.e. secondTask() should wait for completion of Task1 i.e. firstTask(). Run above example and notice the sequence in which output appears on the console. 

Please note few important points

  1. Any task that calls await() on the object will block until the count reaches zero or it's interrupted by another thread. secondTask() gets blocked after call to await(); evident from output.
  2. Call countDown() on the object to reduce the count. The task that call countDown() are not blocked.  This cal signals the end of the task. This method need to be called at the end of the task.
  3. As soon as count reaches zero; threads awaiting starts running. 
  4. The value of count which is passed during creation of latch object is very important. It should be same as the number of task which needs to be finished first. If count is 5 then first task should be called five times to make sure that count has reduced to 0.
  5. You can also use wait and notify mechanism of Java to achieve the same behavior but code will become quite complicated. 
  6. One of the disadvantage of CountDownLatch is that its not reusable once count reaches to zero. But Java provides another concurrency API called CyclicBarrier for such cases. 

Usage of CountDownLatch

  1. Use this when your current executing thread/main thread needs to wait for the completion of other dependent activities. 
  2. Ensure that a service doesn't start until other services on which it depends have not completed.
  3. In a multi-player game like RoadRash; wait for all players to get ready to start the race. 

---
do post your comments/questions !!!