1 inheritance diagram
2 Runnable interface
The Runnable interface is a thread helper class that defines only one method, the run() method.
Flexible: Runnable can inherit other classes to implement the enhancement of Runnable implementation classes, avoiding the problem that Thread class cannot inherit other classes because it inherits Thread class.
Shared resources: the run() method of the Runnable interface can be shared by multiple threads. It is suitable for multiple processes to deal with a resource.
The difference between Runnable and Thread:
(1)Runnable The implementation method of is to implement its interface (2)Thread Is implemented by inheriting its classes (3)Runnable The interface supports multiple inheritance (4)Thread Realized Runnable Interface and extended, and Thread and Runnable The essence of is the relationship of realization, not the same thing, so Runnable or Thread There is no comparability in itself.
@FunctionalInterface public interface Runnable { // function public abstract void run(); }
3Future interface
The Future interface is the implementation of the Future pattern of Java threads, which can be used for asynchronous computing.
Future The pattern can be described as follows: I have a task submitted to Future,Future Finish the task for me, during which I can do whatever I want. After some time, I can start from Future Take the results there. Future The interface provides methods to detect whether the task has been executed, wait for the result to be obtained after the task is executed, or set the timeout of task execution. The way to set the timeout is to implement Java The key to program execution timeout. Future Interface is a generic interface. The strict format should be Future<V>,among V Represents Future The type of return value of the task executed.
public interface Future<V> { // Cancel asynchronous task execution: if the asynchronous task has been completed or cancelled, or cannot be cancelled for some reasons, false will be returned; // If the task has not been executed, it will return true and the asynchronous task will not be executed; // If the task has been started but not completed: if mayInterruptIfRunning is true, the thread executing the task will be immediately interrupted and return true; if mayInterruptIfRunning is false, it will return true and the task execution thread will not be interrupted. boolean cancel(boolean mayInterruptIfRunning); // Judge whether the task is cancelled: if the task is cancelled before the end (normal execution or abnormal execution), return true; otherwise, return false. boolean isCancelled(); // Judge whether the task has been completed. If it is completed, return true; otherwise, return false. It should be noted that if an exception occurs during task execution and the task is cancelled, the task has been completed, and true will also be returned. boolean isDone(); // Get the task execution result. If the task is not completed, it will block and wait until the task execution is completed. // If the task is cancelled, a cancelationexception will be thrown. If an exception occurs during the execution of the task, an ExecutionException will be thrown. If the blocking waiting process is interrupted, an InterruptedException exception will be thrown. V get() throws InterruptedException, ExecutionException; // In the get() version with timeout, if the timeout is exceeded during the blocking wait process, a TimeoutException exception will be thrown. V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
4Callable interface
The function of the Callable interface is similar to that of the Runnable interface. Executing the call method in the Callable object can throw a Checked Exception. You can obtain the return value of task execution; By combining with Future, we can use Future to track the results of asynchronous computing.
Callable and Runnable differ in the following points:
(1),Callable The prescribed method is call(),and Runnable The prescribed method is run() (2),Callable Can return a value after the task is executed, and Runnable The task cannot return a value (3),call()Method can throw an exception, and run()Methods cannot throw exceptions (4),function Callable You can get one for the task Future object,Get the execution result of the thread
@FunctionalInterface public interface Callable<V> { // If the calculation result cannot be executed, an exception is thrown V call() throws Exception; }
5FutureTask class
FutureTask is a task that provides the results of asynchronous calculations. FutureTask can be used to wrap Callable or Runnbale objects. Because FutureTask implements the Runnable interface, FutureTask can also be submitted to the Executor (as in the above example).
In addition to implementing the Future interface, FutureTask also implements the Runnable interface. Therefore, FutureTask can be executed by the Executor or directly called by thread (futureTask.run()). According to the execution time of the run method of FutureTask, FutureTask can be in the following three execution states:
1,Not started: on FutureTask.run()Before it's executed, FutureTask Is not started. When creating a FutureTask Object, and run()Before the method is executed, FutureTask Is not started. 2,Started: FutureTask Object run When the method is started and executed, FutureTask Is started. 3,Completed: FutureTask Normal execution ends, or FutureTask Execution cancelled(FutureTask object cancel method),perhaps FutureTask object run Method execution throws an exception and ends with an interrupt, FutureTask Are in the completed state.
When FutureTask is not started or started, calling the get method of FutureTask object will cause the calling thread to block. When FutureTask is in the completed state, the get method calling FutureTask will immediately put back the call result or throw an exception.
When FutureTask is not started, calling the cancel method of FutureTask object will cause the thread to never be executed;
When FutureTask is in the started state, calling the cancel(true) method of FutureTask object will attempt to stop the task by interrupting the thread executing the task;
When FutureTask is started, calling the cancel(false) method of FutureTask object will not have any impact on the ongoing task;
When FutureTask is in the completed state, calling the cancel method of FutureTask object will return false;
FutureTask can be handed over to the Executor for execution; You can also call executorservice The submit (...) method returns a FutureTask, and then executes the FutureTask.get() method or FutureTask Cancel (...) method. In addition, FutureTask can be used alone.
When a thread needs to wait for another thread to finish executing a task before it can continue to execute, FutureTask can be used. Suppose there are multiple threads executing several tasks, and each task can only be executed once at most. When multiple threads attempt to execute the same task at the same time, only one thread is allowed to execute the task, and other threads need to wait for the task to execute before continuing.
The key to the implementation of the get method is the awaitDone(boolean timed, long nanos) method. The main data structure is the Waiter node plus waiters (top of the stack). The stack stores the threads waiting for the results to achieve the blocking function!!! Note: last in first out
1 member variable
public class FutureTask<V> implements RunnableFuture<V> { /** * The running status of the current task. * * Possible state transitions * NEW -> COMPLETING -> NORMAL((with normal results) * NEW -> COMPLETING -> EXCEPTIONAL((the result is abnormal) * NEW -> CANCELL * ED((no results) * NEW -> INTERRUPTING -> INTERRUPTED((no results) */ private volatile int state; private static final int NEW = 0; //Indicates a new task or a task that has not been completed. This is the initial state. private static final int COMPLETING = 1; //The task has been executed or an exception occurs when the task is executed, but the task execution result or exception reason has not been saved to the outcome field // (the outcome field is used to save the task execution result. If an exception occurs, it is used to save the exception reason.) // The status will change from NEW to COMPLETING. However, this state will take a short time and belongs to the intermediate state. private static final int NORMAL = 2; // The task has been executed and the task execution result has been saved to the outcome field. The status will change from COMPLETING to NORMAL, which is the final status. private static final int EXCEPTIONAL = 3; // After an exception occurs during task execution and the reason for the exception has been saved in the outcome field, the status will be changed from COMPLETING to EXCEPTIONAL, which is the final status. private static final int CANCELLED = 4; // When the task has not started or has started but has not been completed, the user calls the cancel(false) method to cancel the task without interrupting the task execution thread. At this time, the state will change from NEW to CANCELLED, which is a final state. private static final int INTERRUPTING = 5; // When the task has not started or has been executed but has not been completed, the user calls the cancel(true) method to cancel the task and interrupt the task execution thread, but before the task execution thread is interrupted, the state will change from NEW to INTERRUPTING, which is an intermediate state. private static final int INTERRUPTED = 6; //After calling interrupt() to interrupt the task execution thread, the state will transition from INTERRUPTING to INTERRUPTED, which is a final state. All values greater than COMPLETING The status of indicates that the task has been completed(The normal execution of the task is completed, the task execution is abnormal, or the task is cancelled; //Tasks to be performed private Callable<V> callable; //It is used for the result returned by get() or the exception thrown by get() method private Object outcome; // non-volatile, protected by state reads/writes //The thread executing callable calls futuretask The run () method is set through CAS private volatile Thread runner; //The waiting queue of the stack structure. This node is the topmost node in the stack (the thread stack waiting for the result!!!) private volatile WaitNode waiters; // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long stateOffset; private static final long runnerOffset; private static final long waitersOffset; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> k = FutureTask.class; stateOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("state")); runnerOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("runner")); waitersOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("waiters")); } catch (Exception e) { throw new Error(e); } } }
static final class WaitNode { // Note: the following two variables are modified by volatile // Wait for the thread corresponding to the node volatile Thread thread; // Successor node volatile WaitNode next; WaitNode() { thread = Thread.currentThread(); } }
2 construction method
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } public FutureTask(Runnable runnable, V result) { // Through executors Callable() combines runnable and result into a callable this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }
3Run()
(1)Judge the of the current task state Is equal to NEW,If not NEW It indicates that the task has either been executed or cancelled. Return directly. (2)If the status is NEW,Then it will pass unsafe Class references the task execution thread CAS Saved in runner Field. If saving fails, it will be returned directly. (3)Perform the task. (4)If an exception occurs during task execution, call setException()Method to save exception information.
The atomicity of state changes is guaranteed by CAS operations provided by the unsafe object
4awaitDone(boolean timed, long nanos)
awaitDone is the key method to implement blocking in future task
1,calculation deadline,That is, if no result is returned after a certain point in time, it will timeout. 2,Go into spin, that is, dead cycle. 3,First, determine whether to respond to thread interrupt. The response to thread interruption is often placed before the thread enters blocking. 4,judge state Value, if>COMPLETING It indicates that the task has been cancelled or executed, and you can return directly. 5,If the task is still executing, initialize a wait node for the current thread WaitNode,Enter the waiting queue. Here and AQS The waiting queue of is similar to that of, except that: 6,Node Only threads are associated, not states. AQS The waiting nodes inside are stateful. 7,calculation nanos,Determine whether it has timed out. If it has timed out, remove all waiting nodes and return directly state. If you time out, state The value of is still COMPLETING. 8,If you haven't timed out, pass LockSupprot Class to suspend the current thread within a specified time and wait for the task thread to wake up or wake up after timeout.
Exit at:
(1)The thread is interrupted and an exception is thrown (2)The task may have been completed or cancelled, and will wait for the node to finish thread Empty, return state s (3)Timeout, return status
After the user implements the Callable() interface to define the task, the task is handed over to other threads for execution. FutureTask internally maintains a task state. Any operation is carried out around this state and updates the task state at any time. When the task initiator calls get() to get the execution result, if the task has not been completed, it will put itself into the blocking queue and wait for blocking. When the task execution is completed, the task execution thread will wake up the blocked waiting threads in turn. When you call cancel() to cancel a task, you simply modify the task state. If you need to interrupt the task execution thread, you call thread Interrupt() interrupts the task execution thread.