FutureTask类的get方法如何实现线程同步等待

  在JDK中实现线程同步等待闭环(FutureTask/Future),为什么使用了FutureTask中的get方法就可以实现线程的同步等待?这就将重点讲述下FutureTask这个类了,实际上Future接口和实现Future接口的FutureTask,表示异步算的果。其UML类继承图,如下:

            

  从上图看FutureTask除了实现Future接口外,还实现Runnable接口。因此,FutureTask可以交给Executor行,也可以由线程直接行(FutureTask.run())。根据FutureTask.run()方法被机,FutureTask可以于下面3种状态(线程状态转换参考线程基本方法及其对线程状态的影响 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)):

    1)未启FutureTask.run()方法没有被行之前,FutureTask于未启。当建一个FutureTask,且没有FutureTask.run()方法之前,FutureTask于未启

    2)已启FutureTask.run()方法被行的程中,FutureTask于已启

    3)已完成。FutureTask.run()方法行完后正常束,或被取消(FutureTask.cancel)),或FutureTask.run()方法抛出异常而异常束,FutureTask于已完成状。

            

             

   FutureTask于未启或已启态时FutureTask.get()方法将线程阻塞;当FutureTask于已完成状态时FutureTask.get()方法将线程立即返回果或抛出异常——非常类似于闭锁的语义。

  看看get()方法的实现:

            

   通过源码可以看到:get()方法使用AQS类型的同步状态来持有任务的状态——运行、完成或者取消(state变量),同时利用state变量也维护了一些额外的状态变量来持有计算的结果或者抛出异常。与利用AQS类实现同步器的类是不是似曾相识(#^.^#),所以FutureTask虽然代表异步执行的结果,但是可以通过get方法阻塞当前正在运行的线程实现同步等待异步结果。

  其还维护一个WaitNode q 指向正在运行计算任务的线程(当前正处于运行状态),这样任务被取消就可以终止该线程:

            

   get()方法的执行示意图如下图上半部分:

            

 

   

posted on 2021-12-29 15:41  池塘里洗澡的鸭子  阅读(1249)  评论(0编辑  收藏  举报