First, callable and Runnable
Let's talk about Java.lang.Runnable, it's an interface that only declares a run () method in it:
Public Interface Runnable { publicabstractvoid run ();}
Because the run () method returns a value of type void, No results can be returned after the task has been executed .
Callable is located under the Java.util.concurrent package, which is also an interface, in which only one method is declared, but this method is called call ():
Public Interface Callable<v> { /** * Computes a result, or throws an exception if unable to does so. * @return computed result @throws Exception If unable to compute a Result * /throws Exception;}
As you can see, this is a generic interface that declares a method named Call (), which can either have a return value of V or throw an exception. The type returned by the call () method is the type of V passed in.
So how do you use callable? Typically used in conjunction with Executorservice, the overloaded versions of several submit methods are declared in the Executorservice interface:
<T> future<t> Submit (callable<t> Task); <T> future<t> Submit (Runnable task, T result); Future <?> Submit (Runnable Task);
The first method: Submit submits a task that implements the callable interface, and returns a future that encapsulates the results of an asynchronous calculation.
The second method: Submit submits a task that implements the Runnable interface, and specifies the result object that is returned when the Get method of the future is called.
The third method: Submit submits a task that implements the Runnable interface, and returns a future that encapsulates the results of an asynchronous calculation.
So all we have to do is create our threading object (implement the callable interface or runnable interface) and then commit to the thread pool by the 3 methods above.
Second, future
The future is to cancel the execution result of the specific runnable or callable task, whether the query is completed, and the result is obtained. If necessary, the result of the execution can be obtained through the Get method, which blocks until the task returns the result .
The Future<v> interface is used to get the results of an asynchronous calculation, which is to get (get ()), to cancel (cancel ()), to determine whether the specific runnable or callable object task execution results are done. Let's look at the source of the Future interface:
Public Interface Future<v> { boolean Cancel (boolean mayinterruptifrunning); Boolean iscancelled (); Boolean IsDone (); throws interruptedexception, executionexception; V Get (long timeout, timeunit unit) throws interruptedexception, Executionexception, timeoutexception;}
5 methods are declared in the future interface, which in turn explains the function of each method:
- The Cancel method is used to cancel the task and returns true if the Cancel task succeeds, or False if the cancel task fails. The parameter mayinterruptifrunning indicates whether a task that is executing but not completed is allowed to be canceled, and if set to true, it means that the task in the process of execution can be canceled. If the task is completed, whether mayinterruptifrunning is true or FALSE, this method will definitely return false, that is, if canceling the completed task returns false, or if the task is executing, Returns True if the mayinterruptifrunning is set to true, or False if the mayinterruptifrunning is set to False, or if the task has not been executed, Returns true regardless of whether mayinterruptifrunning is true or false.
- The IsCancelled method indicates whether the task was canceled successfully and returns true if the task was canceled successfully before it was properly completed.
- The Isdone method indicates whether the task has completed and returns true if the task completes;
- The Get () method is used to get the result of the execution, this method will be blocked, will wait until the task is completed before returning ;
- Get (long timeout, timeunit unit) is used to get the execution result, and if the result is not obtained within the specified time, NULL is returned directly.
This means that the future offers three functions:
1) Determine whether the task is completed;
2) ability to interrupt tasks;
3) Ability to get task execution results.
Because the future is just an interface, it is not directly used to create objects, so there is the following futuretask.
Third, Futuretask
Let's take a look at the implementation of Futuretask:
Public class Implements Runnablefuture<v>
The Futuretask class implements the Runnablefuture interface, and we look at the implementation of the Runnablefuture interface:
Public Interface extends Runnable, future<v> { void run ();}
It can be seen that runnablefuture inherits the Runnable interface and the future interface, and Futuretask implements the Runnablefuture interface. so it can be executed as runnable by thread, and can get callable return value as future.
Analysis:
Futuretask In addition to the implementation of the future interface also implements the Runnable interface, so futuretask can also be directly submitted to executor execution. Of course, you can also invoke the thread to execute directly (Futuretask.run ()). Next we analyze the 3 states that are in place based on the timing of Futuretask.run ():
(1) Not started, the Futuretask.run () method has not been executed before, Futuretask is in the not-started state when a futuretask is created, and no Futuretask.run () method is executed before the This futuretask is also in a non-bootable state.
(2) started, Futuretask.run () was executed during the process, Futuretask was in the started state.
(3) completed, the Futuretask.run () method completes the normal end, or is canceled or throws an exception to end, Futuretask are in the completed state.
Let's take a look at the Futuretask method execution (the method and the future interface are basically the same, here is not too much to describe)
Analysis:
(1) When Futuretask is in the not-started or started state, if we execute the Futuretask.get () method at this time, the calling thread will be blocked, and when Futuretask is in the completed state, Futuretask.get () is executed. method causes the calling thread to return the result immediately or throw an exception.
(2) When Futuretask is in an inactive state, the Execute Futuretask.cancel () method will cause this task to never execute. When Futuretask is in the started state, the Cancel (true) method attempts to stop the task in a manner that interrupts the execution of this task thread, and if the task cancels successfully, cancel (...) Returns true, but if execution of the Cancel method will not affect the executing task thread (let the thread perform to completion), Cancel (...) at this point. returns FALSE. When the task is complete, execute cancel (...) Method will return false.
Finally, we give two constructors for Futuretask:
Public Futuretask (callable<v> callable) {} public futuretask (Runnable Runnable, V result) {}
In fact, Futuretask is a unique implementation class for the future interface.
Iv. Examples of Use
Through the above introduction, we have a relatively clear understanding of the callable,future,futuretask, then what is the use of them in the end? We said earlier that in this way to create a thread, the biggest benefit is to be able to return the results , to join the scene, we now need to calculate a data, and the calculation of this data is more time-consuming, and our subsequent program will use this data results, So this time callable is not the best choice? We can open a thread to perform the calculation, and the main thread continues to do other things, and when we need to use this data later, we can use the future to get it? Let's write an example like this.
1. Use Callable+future to get execution results
Packagecom.demo.test;Importjava.util.concurrent.Callable; Public classTaskImplementsCallable<integer>{@Override PublicInteger Call ()throwsException {System.out.println ("Child threads are being evaluated"); Thread.Sleep (3000); intsum = 0; for(inti=0;i<100;i++) Sum+=i; returnsum; }}
Packagecom.demo.test;Importjava.util.concurrent.ExecutionException;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;Importjava.util.concurrent.Future; Public classCallabletest { Public Static voidMain (string[] args) {//Create a thread poolExecutorservice executor =Executors.newcachedthreadpool (); //Create a Callable object taskTask task =NewTask (); //submit tasks and get execution resultsfuture<integer> result =Executor.submit (Task); //Close the thread poolExecutor.shutdown (); Try{Thread.Sleep (1000); } Catch(interruptedexception E1) {e1.printstacktrace (); } System.out.println ("Main thread is performing tasks"); Try { if(Result.get ()! =NULL) {System.out.println ("Task Run Result" +result.get ()); }Else{System.out.println ("No results obtained"); } } Catch(interruptedexception e) {e.printstacktrace (); } Catch(executionexception e) {e.printstacktrace (); } System.out.println ("All Tasks Completed"); }}
Operation Result:
The child thread performs the task in the main thread of the calculation 4950 all tasks are completed
2. Use Callable+futuretask to get execution results
Packagecom.demo.test;Importjava.util.concurrent.ExecutionException;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;ImportJava.util.concurrent.FutureTask; Public classCallableTest1 { Public Static voidMain (string[] args) {//The first wayExecutorservice executor =Executors.newcachedthreadpool (); Task Task=NewTask (); Futuretask<Integer> Futuretask =NewFuturetask<integer>(Task); Executor.submit (Futuretask); Executor.shutdown (); //The second way, note that this approach is similar to the first, except that one is using Executorservice, one using 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 ("Main thread is performing tasks"); Try { if(Futuretask.get ()! =NULL) {System.out.println ("Task Run Result" +futuretask.get ()); }Else{System.out.println ("Future.get () failed to get results"); } } Catch(interruptedexception e) {e.printstacktrace (); } Catch(executionexception e) {e.printstacktrace (); } System.out.println ("All Tasks Completed"); }}
The results of the operation are as above.
Add:
The difference between implementing the Runnable interface and implementing the callable interface:
1, runnable is since java1.1 has, and callable is 1.5 after add to.
2, callable prescribed method is call (), runnable the method is defined by run ().
3. Callable's task can return a value after execution, and Runnable's task is not to return a value (is void).
4, the call method can throw an exception, the Run method can not.
5. Run the callable task to get a future object that represents the result of an asynchronous calculation. It provides a way to check whether the calculation is complete, to wait for the completion of the calculation, and to retrieve the results of the calculation. The future object enables you to understand task execution, cancel the execution of a task, and get execution results.
6, join the thread pool run, runnable use Executorservice's Execute method, callable use the Submit method.
Java Concurrency Programming: callable, Future, and Futuretask