Future, callable and futureTask usage

1. Callable and Runnable
  Let’s talk about java.lang.Runnable first, it is an interface, and only one run() method is declared in it:

1
2
3
public interface Runnable {
    public abstract void run();
}
  Because run( ) method returns a void type, so it cannot return any results after executing the task.

  Callable is located in the java.util.concurrent package, it is also an interface, and only one method is declared in it, but this method is called call():

1
2
3
4
5
6
7
8
9
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}
  As you can see, this is a generic interface, and the type returned by the call() function is the type of V passed in.

  So how to use Callable? In general, it is used in conjunction with ExecutorService. Several overloaded versions of submit methods are declared in the ExecutorService interface:

1
2
3
<T> Future<T> submit(Callable<T> task);
<T> Future<T > submit(Runnable task, T result);
Future<?> submit(Runnable task);
  The parameter type in the first submit method is Callable.

  For the time being, you only need to know that Callable is generally used in conjunction with ExecutorService. The specific usage will be described later.

  In general, we use the first submit method and the third submit method, and the second submit method is rarely used.

2.
  Future Future is to cancel the execution result of a specific Runnable or Callable task, query whether it is completed, and obtain the result. If necessary, the execution result can be obtained through the get method, which will block until the task returns the result.

  The Future class is located in java.util.





5
6
7
8
public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException , TimeoutException;
}
  5 methods are declared in the Future interface, and the function of each method is explained in turn:

The cancel method is used to cancel the task. It returns true if the cancel task is successful, and returns false if the cancel task fails. The parameter mayInterruptIfRunning indicates whether it is allowed to cancel the task that is being executed but not completed. If it is set to true, it indicates that the task in the execution process can be canceled. If the task has been completed, whether mayInterruptIfRunning is true or false, this method must return false, that is, if the completed task is canceled, it will return false; if the task is executing, if mayInterruptIfRunning is set to true, it will return true, if mayInterruptIfRunning is set to false , then returns false; if the task has not been executed, whether mayInterruptIfRunning is true or false, it must return true.
The isCancelled method indicates whether the task was canceled successfully, and returns true if the task is canceled successfully before the task is completed normally.
The isDone method indicates whether the task has been completed. If the task is completed, it returns true; the
get() method is used to obtain the execution result. This method will block and will not return until the task is executed;
get(long timeout, TimeUnit unit) uses To get the execution result, if the result has not been obtained within the specified time, it will directly return null.
  That is to say, Future provides three functions:

  1) Determine whether the task is completed;

  2) Can interrupt the task;

  3) Can obtain the task execution result.

  Because Future is just an interface, it cannot be used to create objects directly, so there is the following FutureTask.

3. FutureTask
  Let's take a look at the implementation of FutureTask:

1
public class FutureTask<V> implements RunnableFuture<V>
  The FutureTask class implements the RunnableFuture interface, let's take a look at the implementation of the RunnableFuture interface:

1
2
3
public interface RunnableFuture<V> extends Runnable, Future< V> {
    void run();
}
  It can be seen that RunnableFuture inherits Runnable interface and Future interface, and FutureTask implements RunnableFuture interface. So it can be executed by the thread as a Runnable (the run method is automatically called when it is used as a thread), and it can be used as a Future to get the return value of Callable.

  FutureTask provides two constructors:

1
2
3
4
public FutureTask(Callable<V> callable) {
}
public FutureTask(Runnable runnable, V result) {
}
  In fact, FutureTask is the only implementation class of the Future interface.

4. Example of use
  1. Use Callable+Future to get the execution result

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        Future<Integer> result = executor.submit(task);
        executor.shutdown();
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        
        System.out.println("The main thread is executing the task");
        
        try {
            System.out.println("task running result"+result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        
        System.out.println("All tasks completed");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("The child thread is calculating");
        Thread.sleep(3000);
        int sum = 0;
        for(int i= 0;i<100;i++)
            sum += i;
        return sum;
    }
}
  Execution result:

View Code
  2. Use Callable+FutureTask to get the execution result

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class Test {
    public static void main(String[] args) {
        //第一种方式
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        executor.submit(futureTask);
        executor.shutdown();
        
        //The second method, note that this method is similar to the first method, except that one uses ExecutorService and the other uses Thread
        /*Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        Thread thread = new Thread(futureTask); thread.start
        ();*/
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        
        System .out.println("The main thread is executing the task");
        
        try {
            System.out.println("task running result"+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        
        System.out.println("All tasks are executed");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("Sub thread while doing computation");
        Thread.sleep(3000);
        int sum = 0;
        for(int i=0;i<100;i++)
            sum += i;
        return sum;
    }
}
  If Future is used for cancelability but Without providing a usable result, you can declare a Future<?> formal type and return null as the result of the underlying task.

Reprint address: http://www.cnblogs.com/dolphin0520/p/3949310.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326204482&siteId=291194637