We usually start a new child thread to execute time-consuming code , It's very simple to use , Just encapsulate the time-consuming code in the Runnable Medium run() In the method , Then call thread.start() Just fine .
But I believe a lot of people have such needs sometimes , It is to get the result of the child thread running ,
For example, the client calls the service remotely ( Time consuming service ), We need to get the result returned by the calling service , What should I do ? Obviously, the child thread runs run() Method is to return no value . This is the time Future The role of the .

Future How to use it to get the result of running a child thread ? By the way Callable Interface ,Callable Produce results ,Future Get the results . How do you use both of them to get the running results of a child thread ? Let's start with a simple example .
package test; import java.util.concurrent.Callable; import
java.util.concurrent.ExecutionException; import
java.util.concurrent.FutureTask; public class CallableFutureTest { public
static void main(String[] args) { long startTime = System.currentTimeMillis();
Callable<Integer> calculateCallable = new Callable<Integer>() { @Override
public Integer call() throws Exception { // TODO Auto-generated method stub
Thread.sleep(2000);// Simulation time int result = 1+2; return result; } };
FutureTask<Integer> calculateFutureTask = new FutureTask<>(calculateCallable);
Thread t1 = new Thread(calculateFutureTask); t1.start();
// Join now Thread It is running a time-consuming service that simulates remote calls , And rely on his calculations ( For example, a network calculator ) try {
// Simulate time-consuming tasks , The main thread does its own thing , Embody the advantages of multithreading Thread.sleep(3000); int a = 3+5; Integer result =
calculateFutureTask.get(); System.out.println("result =
"+(a+result));// Simulate the running results of the main thread depending on the child thread long endTime = System.currentTimeMillis();
System.out.println("time = "+(endTime-startTime)+"ms"); } catch
(InterruptedException | ExecutionException e) { // TODO Auto-generated catch
block e.printStackTrace(); } } }
  The results are as follows :



As you can see from the above, it takes about 3s, In fact, it is mainly the main thread sleep(3000) Time spent , If not used Future, And it depends on the results of the thread , The time we may need may be 5s( Child thread 2s+ Main thread 3s). Next, we will understand how the above code works from the perspective of source code .

1, Let's look at the class FureTask Class diagram



FutureTask Yes RunnableTask Interface ,RunnableTask Inherited Runnable and Future Interface ( Interfaces support multiple inheritance )


2,t1.start() What we do is FutureTask Class run() method , look down FutureTask.run() Method source code
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this,
runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c =
callable;// Constructor passed in calculateCallable if (c != null && state == NEW) { V result;
boolean ran; try { result = c.call();// What is ultimately implemented is callablede.call() method , With return value ran =
true; } catch (Throwable ex) { result = null; ran = false;
setException(ex);// Save the thrown exception } if (ran) set(result);// Save execution results } } finally { //
runner must be non-null until state is settled to // prevent concurrent calls
to run() runner = null; // state must be re-read after nulling runner to
prevent // leaked interrupts int s = state; if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s); } }

3, Executive Callable.call(), That is to say, it has been implemented calculateCallable .call(), obtain call() Results returned

Let's take a look , How to save the execution results , And then it's convenient Future Get to , That's calling set(result) method

4, have a look set(result) method
protected void set(V v) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
COMPLETING)) { outcome = v;// take result Assign to outcome UNSAFE.putOrderedInt(this,
stateOffset, NORMAL); // final state finishCompletion(); } } /** * Removes and
signals all waiting threads, invokes done(), and * nulls out callable. */
// This method , When the execution is complete , awaken get() Method suspended thread , So that get() The method is blocking // Of for Loop can correctly get the result of the execution
private void finishCompletion() { // assert state > COMPLETING; for (WaitNode
q; (q = waiters) != null;) { if (UNSAFE.compareAndSwapObject(this,
waitersOffset, q, null)) { for (;;) { Thread t = q.thread; if (t != null) {
q.thread = null; LockSupport.unpark(t);// Wake up thread } WaitNode next = q.next; if
(next == null) break; q.next = null; // unlink to help gc q = next; } break; }
} done(); callable = null; // to reduce footprint }

final FutureTask Medium outcome Variable is the result of execution


5, Let's take a look FutureTask.get() Method to get the result of execution
//get Method to indicate if the execution process is complete , Get the results of the execution , Otherwise, the current thread is suspended public V get() throws
InterruptedException, ExecutionException { int s = state; if (s <= COMPLETING)
s = awaitDone(false, 0L);// If the status is not complete return report(s);// Returns the result of execution } // Here is the execution state
private volatile int state; private static final int NEW = 0; private static
final int COMPLETING = 1; private static final int NORMAL = 2; private static
final int EXCEPTIONAL = 3; private static final int CANCELLED = 4; private
static final int INTERRUPTING = 5; private static final int INTERRUPTED = 6;
private int awaitDone(boolean timed, long nanos) throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L; WaitNode q =
null; boolean queued = false; for (;;) {// Methods of blocking if (Thread.interrupted()) {
removeWaiter(q); throw new InterruptedException(); } int s = state; if (s >
COMPLETING) { if (q != null) q.thread = null; return s; } else if (s ==
COMPLETING) // cannot time out yet Thread.yield();// Suspend thread , Let go cpu resources else if (q ==
null) q = new WaitNode(); else if (!queued) queued =
UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q); else if
(timed) { nanos = deadline - System.nanoTime(); if (nanos <= 0L) {
removeWaiter(q); return state; } LockSupport.parkNanos(this, nanos); } else
LockSupport.park(this); } } private V report(int s) throws ExecutionException {
Object x = outcome; if (s == NORMAL) return (V)x;// Return results if (s >= CANCELLED)
throw new CancellationException(); throw new ExecutionException((Throwable)x); }
It can be seen from the above several methods ,FutureTask.get() It's a blocking method , Until the operation is completed , The execution result of the thread .

,INTERRUPTED) These states represent the process of execution , The general implementation process changes as follows :

1) One FutureTask Newly built ,state namely NEW state ;COMPETING and INTERRUPTING Using the progressive tense of , Represents instantaneous state , It's very short-lived ;NORMAL On behalf of the successful completion ;EXCEPTIONAL On behalf of an exception in the execution process ;CANCELED On behalf of the execution process was cancelled ;INTERRUPTED Interrupted

2) The execution process was successfully completed :NEW -> COMPLETING -> NORMAL

3) Exception occurred during execution :NEW -> COMPLETING -> EXCEPTIONAL

4) Execution was cancelled :NEW -> CANCELLED

5) During execution , Thread interrupt :NEW -> INTERRUPTING -> INTERRUPTED

in addition FutureTask There are other ways , as cancel()- cancel ,isDone()- Judge whether the execution is completed ,isCancelled()- Judge whether the execution is cancelled or not , Interested can see the corresponding source code




©2019-2020 Toolsou All rights reserved,
One is called “ Asking for the train ” A small village Finally got the train Spring Boot Lesson 16 :SpringBoot Implementation of multithreading with injection class Chrome OS, For programmers and Windows What does it mean ? Internet Marketing JAVA Convert a string to a numeric type I've been drinking soft water for three years ? What is the use of soft water and water softener You don't know ——HarmonyOS Talking about uni-app Page value transfer problem JavaScript Medium Call and ApplySparkSQL Achieve partition overlay write Character recognition technology of vehicle license plate based on Neural Network