Java Concurrency Programming and Technology Insider: Callable, Future, Futuretask, Completionservice

Source: Internet
Author: User
Tags throwable

Lin Bingwen Evankaka original works. Reprint please specify the source Http://blog.csdn.net/evankaka

In the previous article, I introduced the thread pool and its internal principles. Today, it is mainly about thread-related content. In general, threads implemented with the Runnable interface and thread are not able to return results. However, if you need to return the result of a thread on some occasions. It is necessary to use callable, future, Futuretask, completionservice these classes. Callable can only run in the Executorservice thread pool, but there is a return result, and the execution status can be queried through the returned future object. The future itself is also a design pattern that is used to get the results of asynchronous tasks,

first, the basic source code

So take a look at their source code information

1, callable

Look at its source code:

Public interface Callable<v> {    V call () throws Exception;}

It has only one call method and has a return V, which is generic. It can be thought that returning v here is the result of the thread return.

Executorservice interface: Thread pool execution scheduling framework

<T> future<t> Submit (callable<t> Task);<t> future<t> Submit (Runnable task, T result); Future<?> Submit (Runnable Task);

2. Future

The future is our most common

Public interface Future<v> {    //attempted to cancel execution of this task. If the task is completed, canceled, or cannot be canceled for some other reason, the attempt will fail. When Cancel is called, if the call succeeds and the task has not started     //, the task will never run. If the task is already started, the     //mayinterruptifrunning parameter determines whether the thread that performs this task should be interrupted in a way that attempts to stop the task. After this method returns, subsequent calls to IsDone () will always return true. If this method returns    //returns TRUE, subsequent calls to iscancelled ()//     will always return true.     Boolean Cancel (Boolean mayinterruptifrunning);    Returns true if the task is canceled before it is completed properly.     boolean iscancelled ();   Returns true if the task is completed. This method returns true in all of these cases, possibly due to a normal termination, exception, or cancellation.    boolean isDone ();   Waiting for thread results to return, will block    V get () throws Interruptedexception, Executionexception;   Set timeout time    V get (long timeout, timeunit unit)        throws Interruptedexception, Executionexception, TimeoutException;}

3, Futuretask

From the source to see its inheritance relationship is as follows:




Its source code is as follows:

public class Futuretask<v> implements runnablefuture<v> {//The class that is really used to execute the thread private final sync sync;            Construction Method 1, from callable to create Futuretask public futuretask (callable<v> callable) {if (callable = = null)        throw new NullPointerException ();    sync = new sync (callable); }//Constructor Method 2, from Runnable to create futuretask,v is the thread execution return result public Futuretask (Runnable Runnable, V result) {sync = new sync    (Executors.callable (runnable, result));    }//And Futrue public boolean iscancelled () {return sync.inneriscancelled ();    }//And Futrue public boolean isDone () {return sync.innerisdone (); }//And Futrue public boolean cancel (Boolean mayinterruptifrunning) {return Sync.innercancel (Mayinterruptifru    nning);    }//And Futrue public V get () throws Interruptedexception, Executionexception {return sync.innerget (); }//And Futrue public V get (long timeout, timeunit unit) throws Interruptedexception, Executionexception, TimeoutException {return sync.innerget (Unit.tonanos (timeout));    }//The operation after the end of the thread protected void done () {}//Set the result protected void Set (V V) {Sync.innerset (v);    }//Set exception protected void SetException (Throwable t) {sync.innersetexception (t);    }//thread execution Portal public void run () {sync.innerrun ();    }//Reset protected Boolean Runandreset () {return sync.innerrunandreset (); }//This class is the class that really executes, shuts down the thread private final class Sync extends Abstractqueuedsynchronizer {private static final long        Serialversionuid = -7828117401763700385l;        Thread run state private static final int RUNNING = 1;        private static final int RAN = 2;                private static final int CANCELLED = 4;        Private final callable<v> callable;        Private V result;        Private Throwable exception;        Thread instance private volatile thread runner; Constructor Sync (callable<v> callable) {this.callable = callable;    } 。。。。 }}
The Futuretask class is an implementation of the future and implements the runnable, so it can be executed through the Excutor (thread pool) or passed to the thread object. If you need to do more time-consuming operations in the main thread, but do not want to block the main thread, you can hand these jobs to the future object in the background, when the main thread in the next need, you can get background job calculation results or execution status. The executor framework uses Futuretask to accomplish asynchronous tasks and can be used to perform any potentially time-consuming calculations. The general Futuretask is used for time-consuming computations, and the main thread can get the results after completing its own tasks. The Futuretask class can either use the new thread (Runnable R) to run in one of the threads, or you can use Executorservice.submit (Runnable R) to run in the thread pool, and both ways can get the return result. But the essence is the same, that is, if there is a return result then the constructor must inject a callable object.


Second, the application example

1. Example of future

Package Com.func.axc.futuretask;import Java.util.random;import Java.util.concurrent.callable;import Java.util.concurrent.executionexception;import Java.util.concurrent.executorservice;import  Java.util.concurrent.executors;import java.util.concurrent.future;/** * Function Summary: * * @author Linbingwen * @since June 8, 2016 */public class Futuretest {/** * @author Linbingwen * @since June 8, 2016 * @param args */public static void main (Stri    Ng[] args) {System.out.println ("main Thread begin at:" + system.nanotime ());    Executorservice executor = Executors.newcachedthreadpool ();    Handlecallable Task1 = new Handlecallable ("1");    Handlecallable task2 = new Handlecallable ("2");        Handlecallable task3 = new Handlecallable ("3");        future<integer> result1 = Executor.submit (TASK1);        future<integer> result2 = Executor.submit (TASK2);        future<integer> RESULT3 = Executor.submit (TASK3);        Executor.shutdown ();        try {thread.sleep (1000); }catch (Interruptedexception E1) {e1.printstacktrace ();            } try {System.out.println ("Task1 Run Result:" +result1.get ());            System.out.println ("Task2 Run Result:" +result2.get ());        System.out.println ("Task3 Run Result:" +result3.get ());        } catch (Interruptedexception e) {e.printstacktrace ();        } catch (Executionexception e) {e.printstacktrace (); } System.out.println ("Main Thread finish at:" + system.nanotime ());}} Class Handlecallable implements Callable<integer>{private string Name;public handlecallable (string name) {    THIS.name = name;} @Override public Integer Call () throws Exception {System.out.println ("task" + name + "start calculation"); thread.sleep; int sum = new Random (). nextint; int result = 0;for (int i = 0; i < sum; i++) result + = I;return r    Esult; }}
Execution Result:


2, Futuretask

Method one, to start the thread directly through the new thread

Package Com.func.axc.futuretask;import Java.util.random;import Java.util.concurrent.callable;import Java.util.concurrent.executionexception;import Java.util.concurrent.futuretask;import org.springframework.scheduling.config.task;/** * Function Summary: * * @author Linbingwen * @since May 31, 2016 */public class Futrueta sktest {public static void main (string[] args) {//takes the method of starting the thread directly System.out.println ("Main thread begin at:" + system.nanotime ());        MyTask Task1 = new MyTask ("1");        futuretask<integer> result1 = new futuretask<integer> (TASK1);        Thread thread1 = new Thread (RESULT1);        Thread1.start ();        MyTask Task2 = new MyTask ("2");        futuretask<integer> result2 = new futuretask<integer> (TASK2);        Thread thread2 = new Thread (RESULT2); Thread2.start (); try {thread.sleep (+);} catch (Interruptedexception E1) {e1.printstacktrace ();} try {System.out.println ("Task1 Returns the result:" + result1.get ()); System.out.println ("Task2 return Result:" + result2.get ());} catch (IntErruptedexception e) {e.printstacktrace ();} catch (Executionexception e) {e.printstacktrace ();} System.out.println ("Main Thread finish at:" + system.nanotime ());}} Class MyTask implements callable<integer> {private String name;public mytask (String name) {this.name = name;} @Overridepublic Integer Call () throws Exception {System.out.println ("task" + name + "start calculation"); thread.sleep; int sum = new Random (). nextint; int result = 0;for (int i = 0; i < sum; i++) result + = I;return r Esult;}}

Execution Result:


Method Two, thread pool to start threads

Package Com.func.axc.futuretask;import Java.util.random;import Java.util.concurrent.callable;import Java.util.concurrent.executionexception;import Java.util.concurrent.executorservice;import  Java.util.concurrent.executors;import java.util.concurrent.future;/** * Function Summary: * * @author Linbingwen * @since May 31, 2016 */public class FutrueTaskTest2 {public static void main (string[] args) {System.out.println ("main Thread of Begin at:" + syste M.nanotime ()); Executorservice executor = Executors.newcachedthreadpool (); MyTask2 Task1 = new MyTask2 ("1"); MyTask2 task2 = new MyTask2 ("2"); future<integer> result1 = Executor.submit (TASK1); future<integer> result2 = Executor.submit (Task2); Executor.shutdown (); try {thread.sleep ()} catch ( Interruptedexception E1) {e1.printstacktrace ();} try {System.out.println ("Task1 Returns the result:" + result1.get ()); System.out.println ("Task2 return Result:" + result2.get ());} catch (Interruptedexception e) {e.printstacktrace ();} catch (Executionexception e) {e.printstacktrace ();} SystEm.out.println ("Main Thread finish at:" + system.nanotime ());}} Class MyTask2 implements callable<integer> {private String name;public MyTask2 (String name) {this.name = name;} @Overridepublic Integer Call () throws Exception {System.out.println ("task" + name + "start calculation"); thread.sleep; int sum = new Random (). nextint; int result = 0;for (int i = 0; i < sum; i++) result + = I;return r Esult;}}
Execution Result:


Third, Completionservice

This light looks at its words, it can be guessed that it should be a thread after the completion of the relevant services, yes. It is a class that puts the results of the thread pool execution into a blockqueueing. So how does it differ from the future or the Futuretask? In fact, in the above example, the author may not be very good examples. If we use future or futuretask in the thread pool to get the return result, for example. We've opened 100 threads. However, the execution time of these threads is unknown. But we also need to return the results. Each thread executes a corresponding action based on the result. If it is a future or futuretask. We can only pass through a loop, constantly traversing the thread constructor threads. Gets its execution status. And then we'll get the results. This efficiency is too low, it is possible that a thread has finished executing, but we cannot immediately know that it has been processed. It has to be judged by a cycle. Basic above this problem, so out of Completionservice.

The Completionservice principle is not very difficult, it is to put a set of thread execution results into a blockqueueing. The order in which threads are executed in the Blockqueue is only related to the execution time of the thread. independent of their boot order. And you don't have to write yourself a lot to decide which thread is going to do it, and it will do it for you.

First look at its source code:

Package Java.util.concurrent;public interface Completionservice<v> {    //Submit thread Task    future<v> submit ( callable<v> task);    Submit Thread Task    future<v> submit (Runnable task, V result);   Blocking wait    future<v> take () throws interruptedexception;   Non-blocking wait    future<v> poll ();   Non-blocking wait with time    future<v> poll (long timeout, timeunit unit) throws interruptedexception;}
The above is just an interface class whose implementation class is as follows:

Package Java.util.concurrent;public class Executorcompletionservice<v> implements completionservice<v> {    Private final Executor executor;//thread pool class private final abstractexecutorservice AES; Private final blockingqueue<future<v>> completionqueue;//a blocking queue that holds the results of thread execution//a futuretask that is used to thread the threads in the internal package privat E class Queueingfuture extends futuretask<void> {queueingfuture (runnablefuture<v> Task) {s            Uper (task, NULL);        This.task = task; } protected void Done () {Completionqueue.add (Task);}    Calling this function after the thread execution completes puts the result into the blocking queue private final future<v> task; } private runnablefuture<v> Newtaskfor (callable<v> Task) {if (AES = = null) return new Fu        Turetask<v> (Task);    else return aes.newtaskfor (Task); } private runnablefuture<v> Newtaskfor (Runnable task, V result) {if (AES = = null) return new F       Uturetask<v> (task, result); else return aes.newtaskfor (task, result); }//constructor, which is typically passed into a thread pool object Executor implementation class public Executorcompletionservice (Executor Executor) {if (Executor = = nul        L) throw new NullPointerException ();        This.executor = executor;            This.aes = (executor instanceof abstractexecutorservice)?        (Abstractexecutorservice) Executor:null; This.completionqueue = new linkedblockingqueue<future<v>> ();//default is the list block queue}//constructor, you can set the blocking queue public E Xecutorcompletionservice (Executor Executor, blockingqueue<future<v>> compl        Etionqueue) {if (executor = = NULL | | completionqueue = = NULL) throw new NullPointerException ();        This.executor = executor;            This.aes = (executor instanceof abstractexecutorservice)?        (Abstractexecutorservice) Executor:null;    This.completionqueue = Completionqueue; }//Submit thread task, in fact, eventually executor to submit public future<        V> Submit (callable<v> Task) {if (task = = null) throw new NullPointerException ();        runnablefuture<v> f = newtaskfor (Task);        Executor.execute (new Queueingfuture (f));    return F;  }//Submit thread task, in fact eventually executor to submit public future<v> submit (Runnable task, V result) {if (task = = null) throw        New NullPointerException ();        runnablefuture<v> f = newtaskfor (task, result);        Executor.execute (new Queueingfuture (f));    return F;    } public future<v> take () throws Interruptedexception {return completionqueue.take ();    } public future<v> poll () {return completionqueue.poll (); The public future<v> poll (long timeout, timeunit unit) throws Interruptedexception {return completionqueue.    Poll (timeout, unit); }}
From the source can be known. Eventually the thread is still committed to executor, so the constructor requires executor arguments to instantiate. Add a future to the blocking queue after each thread execution completes.

This is the top runnablefuture, which is the thread that is put into the pool every time.

Public interface runnablefuture<v> extends Runnable, future<v> {    void run ();

The following two examples illustrate the use of

1, the difference with the future use:

Customizing a callable

Class Handlefuture<integer> implements callable<integer> {private integer num;public handlefuture (Integer num) {this.num = num;} @Overridepublic Integer Call () throws Exception {Thread.Sleep (3*100); System.out.println (Thread.CurrentThread (). GetName ()); return num;}}
First, Futuer.

public static void Futuretest () throws Interruptedexception, executionexception {System.out.println ("main Thread begin: "); Executorservice executor = Executors.newcachedthreadpool (); list<future<integer>> result = new arraylist<future<integer>> (); for (int i = 0;i<10;i++) { future<integer> Submit = Executor.submit (new handlefuture (i)); Result.add (submit);} Executor.shutdown (); for (int i = 0;i<10;i++) {//One waiting to return the result System.out.println ("return Result:" +result.get (i). get ());} System.out.println ("Main Thread End:");}
Execution Result:


From the output it can be seen that we can only one block out. This will certainly waste a certain amount of time waiting. As 7 returned. But the previous 1-6 did not return. Then 7 will have to wait for 1-6 output to output.

Then change to Completionservice to do:

public static void Completest () throws Interruptedexception, executionexception {System.out.println ("main Thread begin: "); Executorservice executor = Executors.newcachedthreadpool ();//build Complete service completionservice<integer> Completionservice = new executorcompletionservice<integer> (executor); for (int i = 0;i<10;i++) { Completionservice.submit (New Handlefuture (i)); for (int i = 0;i<10;i++) {//One one waits to return the result System.out.println ("return Result:" +completionservice.take (). get ());} System.out.println ("Main Thread End:");}

Output Result:

As you can see, the output of the result is not related to the order in which the threads are placed. After each thread executes successfully, it outputs immediately.




Java Concurrency Programming and Technology Insider: Callable, Future, Futuretask, Completionservice

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.