Since Java 5, Java provides the callable interface. The callable interface provides a call method that can be used as the thread's execution body, but the call method is more powerful than the run method. Mainly reflected in:
1. The call method can return values;
2. The call method can declare that an exception is thrown.Therefore, we can provide a callable object as the target of the thread, and the thread execution body is the call method of the callable object. The problem is that the callable interface is a new interface of Java 5, besides, it does not inherit the runnable interface, so the callable interface cannot be used as the target of the thread directly, and the call method also has a return value. How can we obtain the return value of the call method? Java 5 provides the future interface to represent the return value of the call method in the callable interface. futuretask is the implementation class of future, and futuretask implements the runnable interface. Therefore, when creating a thread, You can import futuretask. In addition, a callable parameter is required when the futuretask is created. As a result, the callable is linked to the thread. The thread actually executes the callable call method, and the return value is obtained by the futuretask, call the get method to obtain the returned value.
Sample Code:
Callable<Integer> c = new Callable<Integer>(){@Overridepublic Integer call() throws Exception{System.out.println("running...");Thread.sleep(2000);return 215;}};FutureTask<Integer> task = new FutureTask<>(c);new Thread(task).start();try{System.out.println("result : "+task.get());}catch (InterruptedException e){e.printStackTrace();}catch (ExecutionException e){e.printStackTrace();}}
As mentioned above, you can call the futuretask method to obtain the call return value. If the call method is time-consuming, isn't the thread that calls the get method always waiting for the call to end? Well, it does.
The thread that calls the get method will be blocked..
The following is a simple analysis of callable and future from the source code Perspective: The callable method has nothing to say,
There is only one call method as the thread's execution body..
public interface Callable<V> { V call() throws Exception;}
The futuretask class implements the runnablefuture interface, while runnablefuture inherits the runnable and future interfaces:
You are familiar with the runnable interface. What method does the future interface provide?
Public interface future <v> {Boolean cancel (Boolean mayinterruptifrunning); // Cancel the call method Boolean iscancelled () associated with the future; // whether the task cancels Boolean isdone (); // whether the task has completed v get () throws interruptedexception and executionexception; // obtain the call method result V get (long timeout, timeunit unit) // set the timeout time, if no result is received after this time, throws interruptedexception, executionexception, timeoutexception ;}
We all know that after the thread is started, the thread's run method will be called, and the thread's run method logic is as follows:
@Override public void run() { if (target != null) { target.run(); } }
That is, to determine whether a target of the runnable type is passed in. If yes, the runnable run method will be executed. Here we pass in the futuretask, so we will call the run method of the futuretask class:
public void run() { sync.innerRun(); }
Only one line of code calls the innerrun method of the sync class, and sync is the internal class of futuretask. We will continue to trace the implementation of this method:
Void innerrun () {If (! Compareandsetstate (ready, running) return; runner = thread. currentthread (); If (getstate () = running) {// recheck after setting thread v result; try {result = callable. call (); // call the callable call method} catch (throwable ex) {setexception (Ex); return ;} set (result );} else {releaseshared (0); // cancel }}
The call method of callable is still called in the innerrun method, and the result is assigned to the result variable. Let's look at the get method of futuretask:
public V get() throws InterruptedException, ExecutionException { return sync.innerGet(); }
The innerget method of sync is called:
V innerGet() throws InterruptedException, ExecutionException { acquireSharedInterruptibly(0); if (getState() == CANCELLED) throw new CancellationException(); if (exception != null) throw new ExecutionException(exception); return result; }
The result variable is returned.
Analysis of callable and Future