Monday 8 July 2013

About Callable, FutureTask and ExecutorService and their Implementation



Callable

Whenever we think about the creation of a Thread then we imagine about Runnable interface. Runnable has a method run with no parameters and no return value.

But suppose we have a situation where we expect/need some value to be returned after completion of a thread, then using Runnable interface will not provide the appropriate solution. For taking care of this specific requirement Callable is an interface introduced in Java 5 and added in java.util.concurrent library. Callable is mainly intended to use with ExecutorService, which is a higher level service than the direct manipulation of Thread. Both Runnable and Callable can be submitted to ExecutorService for (usually asynchronous) execution. Callable is similar to Runnable, but it returns a value.  

Method Summary
 V
call()
          Computes a result, or throws an exception if unable to do so.

Type Parameters:
V - the result type of method call

Future

A 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 result of the computation. The result 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 cancelled. Once a computation has completed, the computation cannot be cancelled.

Method Summary

boolean
cancel(boolean mayInterruptIfRunning)
          Attempts to cancel execution of this task.
 V
get()
          Waits if necessary for the computation to complete, and then retrieves its result.
 V
get(long timeout, TimeUnit unit)
          Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
 boolean
isCancelled()
          Returns
true if this task was cancelled before it completed normally.
 boolean
isDone()
          Returns
true if this task completed.

Future Task


A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements both Future and Runnable, a FutureTask can be submitted to an Executor for execution.

In addition to serving as a standalone class, this class provides protected functionality that may be useful when creating customized task classes.

This class provides the base implementation of Future, with methods to start and cancel a computation, query to see if the computation is complete, and retrieve the result of the computation. The result can only be retrieved when the computation has completed; the get method will block if the computation has not yet completed. Once the computation has completed, the computation cannot be restarted or cancelled. 

Constructor Summary
FutureTask(Callable<V> callable)
          Creates a
FutureTask that will upon running, execute the given Callable.

FutureTask(Runnable runnable, V result)
          Creates a
FutureTask that will upon running, execute the given Runnable, and arrange that get will return the given result on successful completion.

 
Method Summary
 boolean
cancel(boolean mayInterruptIfRunning)
          Attempts to cancel execution of this task.
protected  void
done()
          Protected method invoked when this task transitions to state
isDone (whether normally or via cancellation).
 V
get()
          Waits if necessary for the computation to complete, and then retrieves its result.
 V
get(long timeout, TimeUnit unit)
          Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.
 boolean
isCancelled()
          Returns
true if this task was cancelled before it completed normally.
 boolean
isDone()
          Returns
true if this task completed.
 void
run()
          Sets this Future to the result of its computation unless it has been cancelled.
protected  boolean
runAndReset()
          Executes the computation without setting its result, and then resets this Future to initial state, failing to do so if the computation encounters an exception or is cancelled.
protected  void
set(V v)
          Sets the result of this Future to the given value unless this future has already been set or has been cancelled.
protected  void
setException(Throwable t)
          Causes this future to report an
ExecutionException with the given throwable as its cause, unless this Future has already been set or has been cancelled.

Type Parameters:
Note:- V - The result type returned by this Future's get method

Executor

An object that executes submitted Runnable tasks. This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc. 

An Executor is normally used instead of explicitly creating threads. For example, rather than invoking new Thread(new(RunnableTask())).start() for each of a set of tasks, we may use:

 Executor executor = anExecutor;
 executor.execute(new RunnableTask1());
 executor.execute(new RunnableTask2());

Method Summary
 void
execute(Runnable command)
          Executes the given command at some time in the future.


A thread pool can be described as a bunch of Runnable objects (work queue) and connections of running threads. A thread pool manages a pool of worker threads. The thread pool contains a work queue which holds tasks waiting to get executed. These threads are constantly running and are checking the work query for new work. If there is new work for the execution then they will execute this Runnable.  execute (Runnable r) method is provided by the Thread class for the purpose of adding a new Runnable object to the work queue.

The Executor framework provides example implementation of the java.util.concurrent.Executor interface, e.g. Executors.newFixedThreadPool(int n) which will create thread pool of n worker threads. The ExecutorService adds lifecycle methods to the Executor, which allows to shutdown the Executor and to wait for termination.

ExecutorService


An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.

An ExecutorService can be shut down, which will cause it to reject new tasks.

Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.

Method submit extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion.

All known  implementing classes are AbstractExecutorService, ScheduledThreadPoolExecutor, ThreadPoolExecutor.

Method Summary
 boolean
awaitTermination(long timeout, TimeUnit unit)
          Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
<T> List<Future<T>>
invokeAll(Collection<? extends Callable<T>> tasks)
          Executes the given tasks, returning a list of Futures holding their status and results when all complete.
<T> List<Future<T>>
invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
          Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first.
<T> T
invokeAny(Collection<? extends Callable<T>> tasks)
          Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do.
<T> T
invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
          Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do before the given timeout elapses.
 boolean
isShutdown()
          Returns
true if this executor has been shut down.
 boolean
isTerminated()
          Returns
true if all tasks have completed following shut down.
 void
shutdown()
          Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
 List<Runnable>
shutdownNow()
          Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
<T> Future<T>
submit(Callable<T> task)
          Submits a value-returning task for execution and returns a Future representing the pending results of the task.
 Future<?>
submit(Runnable task)
          Submits a Runnable task for execution and returns a Future representing that task.
<T> Future<T>
submit(Runnable task, T result)
          Submits a Runnable task for execution and returns a Future representing that task.


Implementation Example of Callable, FutureTask and  ExecutorService




package com.gaurav.futuretask.example;

import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.logging.Logger;

class PerformStringReversal {

      private final static Logger logger = Logger
                  .getLogger(PerformStringReversal.class.getName());


      /** This method will allow to perform string reversal in a slow manner */
      public String reverseString(String strOriginalWord) {

            StringBuffer reversedString = new StringBuffer();

            long start = System.nanoTime();

            for (int counter = (strOriginalWord.length() - 1); counter >= 0; counter--) {

                  reversedString.append(strOriginalWord.charAt(counter));

                  logger.info("REVERSING ONE CHARACTER FROM THE GIVEN STRING IN PER SECOND."
                              + reversedString.toString().toUpperCase());

                  logger.info("TOTAL CONSUMED TIME: " + (System.nanoTime() - start)
                              / 1000000 + "ms");

                  try {
                        Thread.sleep(1000);
                  } catch (InterruptedException ie) {
                  }
            }
            return reversedString.toString().toUpperCase();
      }
}

public class FutureTaskImplementation {

      // Using the Java inbuilt logger
      private final static Logger logger = Logger
                  .getLogger(FutureTaskImplementation.class.getName());

      // It creates thread pool of size 1.
      ExecutorService threadPool = Executors.newFixedThreadPool(1);

      PerformStringReversal performStringReversal = new PerformStringReversal();

      public void stringReversel(final String originalStringPassed)
                  throws InterruptedException {

            /**
             * Demonstration of the Callable Interface usage. The return value of
             * the Callable, is stored here as a "Future" type.
             */
            FutureTask<String> futureTask = new FutureTask<String>(

            new Callable<String>() {

                  @Override
                  public String call() {

                        return performStringReversal
                                    .reverseString(originalStringPassed);
                  }
            });
            // Submitting to the thread pool..
            threadPool.submit(futureTask);

            /** Checking the task completion using the isDone() method */
            while (!futureTask.isDone()) {

                  logger.info("TASK IS STILL RUNNING AND NOT YET COMPLETED.");

                  try {

                        Thread.sleep(500);
                  } catch (InterruptedException ie) {
                        logger.severe("CHECKING AFTER 1/2 SEC INTERVAL->"
                                    + ie.getMessage());
                  }
            }
            try {

                  // Getting the result as a Future type.
                  logger.info("THE FINAL RESULT AFTER STRING REVERSAL : -> "
                              + futureTask.get());
            } catch (ExecutionException ex) {
            }
            threadPool.shutdown();
            return;
      }

      public static void main(String args[]) {
            FutureTaskImplementation futureTaskImplementation = new FutureTaskImplementation();

            try {

                  logger.info("ENTER THE STRING FOR WHICH YOU WANT TO CHECK REVERSAL");

                  Scanner scanner = new Scanner(System.in);

                  String originalWord = scanner.nextLine();

                  futureTaskImplementation.stringReversel(originalWord);
            } catch (Exception e) {
                  logger.severe("ERROR IN MAIN METHOD:-> " + e.getMessage());
            }
      }
}


Result:-

Jul 09, 2013 6:47:08 AM com.gaurav.futuretask.example.FutureTaskImplementation main
INFO: ENTER THE STRING FOR WHICH YOU WANT TO CHECK REVERSAL
kumar
Jul 09, 2013 6:47:11 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:11 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: REVERSING ONE CHARACTER FROM THE GIVEN STRING IN PER SECOND : - > R
Jul 09, 2013 6:47:11 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: TOTAL CONSUMED TIME: 1ms
Jul 09, 2013 6:47:11 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:12 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:12 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: REVERSING ONE CHARACTER FROM THE GIVEN STRING IN PER SECOND : - > RA
Jul 09, 2013 6:47:12 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: TOTAL CONSUMED TIME: 1002ms
Jul 09, 2013 6:47:12 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:13 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:13 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: REVERSING ONE CHARACTER FROM THE GIVEN STRING IN PER SECOND : - > RAM
Jul 09, 2013 6:47:13 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: TOTAL CONSUMED TIME: 2004ms
Jul 09, 2013 6:47:13 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:14 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:14 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: REVERSING ONE CHARACTER FROM THE GIVEN STRING IN PER SECOND : - > RAMU
Jul 09, 2013 6:47:14 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: TOTAL CONSUMED TIME: 3007ms
Jul 09, 2013 6:47:15 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:15 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:15 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: REVERSING ONE CHARACTER FROM THE GIVEN STRING IN PER SECOND : - > RAMUK
Jul 09, 2013 6:47:15 AM com.gaurav.futuretask.example.PerformStringReversel reverseString
INFO: TOTAL CONSUMED TIME: 4009ms
Jul 09, 2013 6:47:16 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:16 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: TASK IS STILL RUNNING AND NOT YET COMPLETED.
Jul 09, 2013 6:47:17 AM com.gaurav.futuretask.example.FutureTaskImplementation stringReversel
INFO: THE FINAL RESULT AFTER STRING REVERSAL : -> RAMUK
 
reference taken from:- http://www.oracle.com

No comments:

Post a Comment