Java Concurrency --FutureTask Comments

FutureTask

Future class interface and implementation FutureTask Future interface, representing the result of the asynchronous computation.

About FutureTask

In addition to achieving FutureTask Future interface, but also implements Runnable interface. Therefore, FutureTask to the Executor can execute can be performed (FutureTask.run ()) directly by the calling thread. The timing FutureTask.run () method is executed, FutureTask may be in the following three states.

  • Not started . Before FutureTask.run () method has not been performed, FutureTask in a non-activated state. Before creating a FutureTask, and no execution FutureTask.run () method, this FutureTask in a deactivated state.
  • It has started . Process FutureTask.run () method is executed, FutureTask is in the started state.
  • It has been completed . It throws an exception when FutureTask.run () method to perform after the normal end, or canceled (FutureTask.cancel (...)), or perform FutureTask.run () method ends abnormally, FutureTask a finished state.

FutureTask state migration diagram:

Here Insert Picture Description

  • When FutureTask not started or has been started in the state, the implementation of FutureTask.get () method will cause the calling thread to block;
  • When FutureTask finished state, execution FutureTask.get () method will cause the calling thread returns immediately or throw an exception.
  • When FutureTask in a deactivated state, execution FutureTask.cancel () method will cause this task will never be executed;
  • When FutureTask started in the state, the implementation of FutureTask.cancel (true) method to perform this task will interrupt threads to try to stop the task;
  • When FutureTask started in the state, the implementation of FutureTask.cancel (false) method will have no effect on the thread executing this task (to make progress tasks are performed to complete);
  • When FutureTask in a completed state, performing FutureTask.cancel (...) method returns false.

Performing a schematic view of the get method and cancel method:
Here Insert Picture Description

FutureTask use

  • FutureTask to the Executor can execute;
  • May be (...) method returns a FutureTask by ExecutorService.submit, then perform FutureTask.get () method or FutureTask.cancel (...) method.
  • In addition, it can also be used alone FutureTask.

When a thread needs to wait for another thread to perform a task after it to continue, then you can use FutureTask. Suppose there are multiple threads perform several tasks, each task can only be executed at most once. When multiple threads trying to simultaneously perform the same task, allowing only one thread to perform the task, other threads need to wait after the implementation of this task can continue. Here is an example corresponding to the code.

Here Insert Picture Description

The code performs the following schematic diagram:

Here Insert Picture Description
When two threads attempt to simultaneously perform the same task, if executed 1.3 Thread 2 Thread 1 implementation of 2.1, then the next Thread 2 waits at 2.2 until after executing Thread 1 to 1.4 Thread 2 from 2.2 (FutureTask.get ( ))return.

FutureTask implementation

FutureTask的实现基于AbstractQueuedSynchronizer(以下简称为AQS)。java.util.concurrent中的很多可阻塞类(比如ReentrantLock)都是基于AQS来实现的。AQS是一个同步框架,它提供通用机制来原子性管理同步状态、阻塞和唤醒线程,以及维护被阻塞线程的队列。JDK 6中AQS被广泛使用,基于AQS实现的同步器包括:ReentrantLock、Semaphore、ReentrantReadWriteLock、CountDownLatch和FutureTask。

每一个基于AQS实现的同步器都会包含两种类型的操作,如下:

  • 至少一个acquire操作。这个操作阻塞调用线程,除非/直到AQS的状态允许这个线程继续执行。FutureTask的acquire操作为get()/get(long timeout,TimeUnit unit)方法调用。
  • 至少一个release操作。这个操作改变AQS的状态,改变后的状态可允许一个或多个阻塞线程被解除阻塞。FutureTask的release操作包括run()方法和cancel(…)方法。

基于“复合优先于继承”的原则,FutureTask声明了一个内部私有的继承于AQS的子类Sync,对FutureTask所有公有方法的调用都会委托给这个内部子类。

AQS被作为“模板方法模式”的基础类提供给FutureTask的内部子类Sync,这个内部子类只需要实现状态检查和状态更新的方法即可,这些方法将控制FutureTask的获取和释放操作。具体来说,Sync实现了AQS的tryAcquireShared(int)方法和tryReleaseShared(int)方法,Sync通过这两个方法来检查和更新同步状态。

FutureTask的设计示意图如下图:
Here Insert Picture Description
如图所示,Sync是FutureTask的内部私有类,它继承自AQS。创建FutureTask时会创建内部私有的成员对象Sync,FutureTask所有的的公有方法都直接委托给了内部私有的Sync。

FutureTask.get()方法会调用AQS.acquireSharedInterruptibly(int arg)方法,这个方法的执行过程如下。

  1. 调用AQS.acquireSharedInterruptibly(int arg)方法,这个方法首先会回调在子类Sync中实现的tryAcquireShared()方法来判断acquire操作是否可以成功。acquire操作可以成功的条件为:state为执行完成状态RAN或已取消状态CANCELLED,且runner不为null。
  2. 如果成功则get()方法立即返回。如果失败则到线程等待队列中去等待其他线程执行release操作。
  3. 当其他线程执行release操作(比如FutureTask.run()或FutureTask.cancel(…))唤醒当前线程后,当前线程再次执行tryAcquireShared()将返回正值1,当前线程将离开线程等待队列并唤醒它的后继线程(这里会产生级联唤醒的效果,后面会介绍)。
  4. 最后返回计算的结果或抛出异常。

FutureTask.run()的执行过程如下:

  1. 执行在构造函数中指定的任务(Callable.call())。
  2. 以原子方式来更新同步状态(调用AQS.compareAndSetState(int expect,int update),设置state为执行完成状态RAN)。如果这个原子操作成功,就设置代表计算结果的变量result的值为Callable.call()的返回值,然后调用AQS.releaseShared(int arg)。
  3. AQS.releaseShared (int arg) will first callback (thread runner to run the task set is null, then returns true) tryReleaseShared (arg) to perform the release operation implemented in the sub-class in Sync; AQS.releaseShared (int arg), then wake threads waiting in the queue first thread.
  4. Call FutureTask.done ().

When performing FutureTask.get () method is not performed if the completion status FutureTask RAN or canceled CANCELED state, the currently executing thread to the AQS waiting thread waiting queue (see below the thread A, B, C and D) . When
a thread is executing FutureTask.run () method or FutureTask.cancel (...) method, a thread wakes up the first thread waiting queue (see FIG thread E 10-16 thread wake-A).

Here Insert Picture Description
Suppose the start FutureTask activated state or in a non-activated state, waiting queue has three threads (A, B, and C) waiting. At this time, the thread D executed get () method will also cause the thread to the wait queue D to wait.

When the thread execution E run () method will wake up in the queue first thread A. After thread A wakes up, first of all himself removed from the queue, and then its successor wake thread B, thread A final return from get () method. Thread B, C and D repeats A processing flow of the threads. Ultimately, all threads waiting in the queue are cascaded wake up and return from the get () method.

Published 660 original articles · won praise 1889 · Views 240,000 +

Guess you like

Origin blog.csdn.net/cold___play/article/details/104070980