`
truelove12358
  • 浏览: 77581 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Java中的Callable、Future、FutureTask、Runnable的区别与示例

 
阅读更多

Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。


Runnable

其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中,该函数没有返回值。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。Runnable的声明如下 :

  1. publicinterfaceRunnable{
  2. /**
  3. *Whenanobjectimplementinginterface<code>Runnable</code>isused
  4. *tocreateathread,startingthethreadcausestheobject's
  5. *<code>run</code>methodtobecalledinthatseparatelyexecuting
  6. *thread.
  7. *<p>
  8. *
  9. *@seejava.lang.Thread#run()
  10. */
  11. publicabstractvoidrun();
  12. }

Callable

Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :

  1. publicinterfaceCallable<V>{
  2. /**
  3. *Computesaresult,orthrowsanexceptionifunabletodoso.
  4. *
  5. *@returncomputedresult
  6. *@throwsExceptionifunabletocomputearesult
  7. */
  8. Vcall()throwsException;
  9. }
可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。

Future

Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。Future声明如下 :

  1. /**
  2. *@seeFutureTask
  3. *@seeExecutor
  4. *@since1.5
  5. *@authorDougLea
  6. *@param<V>TheresulttypereturnedbythisFuture's<tt>get</tt>method
  7. */
  8. publicinterfaceFuture<V>{
  9. /**
  10. *Attemptstocancelexecutionofthistask.Thisattemptwill
  11. *failifthetaskhasalreadycompleted,hasalreadybeencancelled,
  12. *orcouldnotbecancelledforsomeotherreason.Ifsuccessful,
  13. *andthistaskhasnotstartedwhen<tt>cancel</tt>iscalled,
  14. *thistaskshouldneverrun.Ifthetaskhasalreadystarted,
  15. *thenthe<tt>mayInterruptIfRunning</tt>parameterdetermines
  16. *whetherthethreadexecutingthistaskshouldbeinterruptedin
  17. *anattempttostopthetask.*
  18. */
  19. booleancancel(booleanmayInterruptIfRunning);
  20. /**
  21. *Returns<tt>true</tt>ifthistaskwascancelledbeforeitcompleted
  22. *normally.
  23. */
  24. booleanisCancelled();
  25. /**
  26. *Returns<tt>true</tt>ifthistaskcompleted.
  27. *
  28. */
  29. booleanisDone();
  30. /**
  31. *Waitsifnecessaryforthecomputationtocomplete,andthen
  32. *retrievesitsresult.
  33. *
  34. *@returnthecomputedresult
  35. */
  36. Vget()throwsInterruptedException,ExecutionException;
  37. /**
  38. *Waitsifnecessaryforatmostthegiventimeforthecomputation
  39. *tocomplete,andthenretrievesitsresult,ifavailable.
  40. *
  41. *@paramtimeoutthemaximumtimetowait
  42. *@paramunitthetimeunitofthetimeoutargument
  43. *@returnthecomputedresult
  44. */
  45. Vget(longtimeout,TimeUnitunit)
  46. throwsInterruptedException,ExecutionException,TimeoutException;
  47. }

FutureTask

FutureTask则是一个RunnableFuture<V>,而RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口,

  1. publicclassFutureTask<V>implementsRunnableFuture<V>
RunnableFuture

  1. publicinterfaceRunnableFuture<V>extendsRunnable,Future<V>{
  2. /**
  3. *SetsthisFuturetotheresultofitscomputation
  4. *unlessithasbeencancelled.
  5. */
  6. voidrun();
  7. }

另外它还可以包装Runnable和Callable<V>, 由构造函数注入依赖。

  1. publicFutureTask(Callable<V>callable){
  2. if(callable==null)
  3. thrownewNullPointerException();
  4. this.callable=callable;
  5. this.state=NEW;//ensurevisibilityofcallable
  6. }
  7. publicFutureTask(Runnablerunnable,Vresult){
  8. this.callable=Executors.callable(runnable,result);
  9. this.state=NEW;//ensurevisibilityofcallable
  10. }
可以看到,Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务。该适配函数的实现如下 :

  1. publicstatic<T>Callable<T>callable(Runnabletask,Tresult){
  2. if(task==null)
  3. thrownewNullPointerException();
  4. returnnewRunnableAdapter<T>(task,result);
  5. }
RunnableAdapter适配器

  1. /**
  2. *Acallablethatrunsgiventaskandreturnsgivenresult
  3. */
  4. staticfinalclassRunnableAdapter<T>implementsCallable<T>{
  5. finalRunnabletask;
  6. finalTresult;
  7. RunnableAdapter(Runnabletask,Tresult){
  8. this.task=task;
  9. this.result=result;
  10. }
  11. publicTcall(){
  12. task.run();
  13. returnresult;
  14. }
  15. }

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。

并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。因此FutureTask既是Future、Runnable,又是包装了Callable( 如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。


简单示例

  1. packagecom.effective.java.concurrent.task;
  2. importjava.util.concurrent.Callable;
  3. importjava.util.concurrent.ExecutionException;
  4. importjava.util.concurrent.ExecutorService;
  5. importjava.util.concurrent.Executors;
  6. importjava.util.concurrent.Future;
  7. importjava.util.concurrent.FutureTask;
  8. /**
  9. *
  10. *@authormrsimple
  11. *
  12. */
  13. publicclassRunnableFutureTask{
  14. /**
  15. *ExecutorService
  16. */
  17. staticExecutorServicemExecutor=Executors.newSingleThreadExecutor();
  18. /**
  19. *
  20. *@paramargs
  21. */
  22. publicstaticvoidmain(String[]args){
  23. runnableDemo();
  24. futureDemo();
  25. }
  26. /**
  27. *runnable,无返回值
  28. */
  29. staticvoidrunnableDemo(){
  30. newThread(newRunnable(){
  31. @Override
  32. publicvoidrun(){
  33. System.out.println("runnabledemo:"+fibc(20));
  34. }
  35. }).start();
  36. }
  37. /**
  38. *其中Runnable实现的是voidrun()方法,无返回值;Callable实现的是V
  39. *call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下
  40. *,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
  41. */
  42. staticvoidfutureDemo(){
  43. try{
  44. /**
  45. *提交runnable则没有返回值,future没有数据
  46. */
  47. Future<?>result=mExecutor.submit(newRunnable(){
  48. @Override
  49. publicvoidrun(){
  50. fibc(20);
  51. }
  52. });
  53. System.out.println("futureresultfromrunnable:"+result.get());
  54. /**
  55. *提交Callable,有返回值,future中能够获取返回值
  56. */
  57. Future<Integer>result2=mExecutor.submit(newCallable<Integer>(){
  58. @Override
  59. publicIntegercall()throwsException{
  60. returnfibc(20);
  61. }
  62. });
  63. System.out
  64. .println("futureresultfromcallable:"+result2.get());
  65. /**
  66. *FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,
  67. *另外它还可以包装Runnable(实际上会转换为Callable)和Callable
  68. *<V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
  69. *,并且还可以通过vget()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
  70. */
  71. FutureTask<Integer>futureTask=newFutureTask<Integer>(
  72. newCallable<Integer>(){
  73. @Override
  74. publicIntegercall()throwsException{
  75. returnfibc(20);
  76. }
  77. });
  78. //提交futureTask
  79. mExecutor.submit(futureTask);
  80. System.out.println("futureresultfromfutureTask:"
  81. +futureTask.get());
  82. }catch(InterruptedExceptione){
  83. e.printStackTrace();
  84. }catch(ExecutionExceptione){
  85. e.printStackTrace();
  86. }
  87. }
  88. /**
  89. *效率底下的斐波那契数列,耗时的操作
  90. *
  91. *@paramnum
  92. *@return
  93. */
  94. staticintfibc(intnum){
  95. if(num==0){
  96. return0;
  97. }
  98. if(num==1){
  99. return1;
  100. }
  101. returnfibc(num-1)+fibc(num-2);
  102. }
  103. }

输出结果


Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。


Runnable

其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中,该函数没有返回值。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。Runnable的声明如下 :

  1. publicinterfaceRunnable{
  2. /**
  3. *Whenanobjectimplementinginterface<code>Runnable</code>isused
  4. *tocreateathread,startingthethreadcausestheobject's
  5. *<code>run</code>methodtobecalledinthatseparatelyexecuting
  6. *thread.
  7. *<p>
  8. *
  9. *@seejava.lang.Thread#run()
  10. */
  11. publicabstractvoidrun();
  12. }

Callable

Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :

  1. publicinterfaceCallable<V>{
  2. /**
  3. *Computesaresult,orthrowsanexceptionifunabletodoso.
  4. *
  5. *@returncomputedresult
  6. *@throwsExceptionifunabletocomputearesult
  7. */
  8. Vcall()throwsException;
  9. }
可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。

Future

Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。Future声明如下 :

  1. /**
  2. *@seeFutureTask
  3. *@seeExecutor
  4. *@since1.5
  5. *@authorDougLea
  6. *@param<V>TheresulttypereturnedbythisFuture's<tt>get</tt>method
  7. */
  8. publicinterfaceFuture<V>{
  9. /**
  10. *Attemptstocancelexecutionofthistask.Thisattemptwill
  11. *failifthetaskhasalreadycompleted,hasalreadybeencancelled,
  12. *orcouldnotbecancelledforsomeotherreason.Ifsuccessful,
  13. *andthistaskhasnotstartedwhen<tt>cancel</tt>iscalled,
  14. *thistaskshouldneverrun.Ifthetaskhasalreadystarted,
  15. *thenthe<tt>mayInterruptIfRunning</tt>parameterdetermines
  16. *whetherthethreadexecutingthistaskshouldbeinterruptedin
  17. *anattempttostopthetask.*
  18. */
  19. booleancancel(booleanmayInterruptIfRunning);
  20. /**
  21. *Returns<tt>true</tt>ifthistaskwascancelledbeforeitcompleted
  22. *normally.
  23. */
  24. booleanisCancelled();
  25. /**
  26. *Returns<tt>true</tt>ifthistaskcompleted.
  27. *
  28. */
  29. booleanisDone();
  30. /**
  31. *Waitsifnecessaryforthecomputationtocomplete,andthen
  32. *retrievesitsresult.
  33. *
  34. *@returnthecomputedresult
  35. */
  36. Vget()throwsInterruptedException,ExecutionException;
  37. /**
  38. *Waitsifnecessaryforatmostthegiventimeforthecomputation
  39. *tocomplete,andthenretrievesitsresult,ifavailable.
  40. *
  41. *@paramtimeoutthemaximumtimetowait
  42. *@paramunitthetimeunitofthetimeoutargument
  43. *@returnthecomputedresult
  44. */
  45. Vget(longtimeout,TimeUnitunit)
  46. throwsInterruptedException,ExecutionException,TimeoutException;
  47. }

FutureTask

FutureTask则是一个RunnableFuture<V>,而RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口,

  1. publicclassFutureTask<V>implementsRunnableFuture<V>
RunnableFuture

  1. publicinterfaceRunnableFuture<V>extendsRunnable,Future<V>{
  2. /**
  3. *SetsthisFuturetotheresultofitscomputation
  4. *unlessithasbeencancelled.
  5. */
  6. voidrun();
  7. }

另外它还可以包装Runnable和Callable<V>, 由构造函数注入依赖。

  1. publicFutureTask(Callable<V>callable){
  2. if(callable==null)
  3. thrownewNullPointerException();
  4. this.callable=callable;
  5. this.state=NEW;//ensurevisibilityofcallable
  6. }
  7. publicFutureTask(Runnablerunnable,Vresult){
  8. this.callable=Executors.callable(runnable,result);
  9. this.state=NEW;//ensurevisibilityofcallable
  10. }
可以看到,Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务。该适配函数的实现如下 :

  1. publicstatic<T>Callable<T>callable(Runnabletask,Tresult){
  2. if(task==null)
  3. thrownewNullPointerException();
  4. returnnewRunnableAdapter<T>(task,result);
  5. }
RunnableAdapter适配器

  1. /**
  2. *Acallablethatrunsgiventaskandreturnsgivenresult
  3. */
  4. staticfinalclassRunnableAdapter<T>implementsCallable<T>{
  5. finalRunnabletask;
  6. finalTresult;
  7. RunnableAdapter(Runnabletask,Tresult){
  8. this.task=task;
  9. this.result=result;
  10. }
  11. publicTcall(){
  12. task.run();
  13. returnresult;
  14. }
  15. }

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。

并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。因此FutureTask既是Future、Runnable,又是包装了Callable( 如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。


简单示例

  1. packagecom.effective.java.concurrent.task;
  2. importjava.util.concurrent.Callable;
  3. importjava.util.concurrent.ExecutionException;
  4. importjava.util.concurrent.ExecutorService;
  5. importjava.util.concurrent.Executors;
  6. importjava.util.concurrent.Future;
  7. importjava.util.concurrent.FutureTask;
  8. /**
  9. *
  10. *@authormrsimple
  11. *
  12. */
  13. publicclassRunnableFutureTask{
  14. /**
  15. *ExecutorService
  16. */
  17. staticExecutorServicemExecutor=Executors.newSingleThreadExecutor();
  18. /**
  19. *
  20. *@paramargs
  21. */
  22. publicstaticvoidmain(String[]args){
  23. runnableDemo();
  24. futureDemo();
  25. }
  26. /**
  27. *runnable,无返回值
  28. */
  29. staticvoidrunnableDemo(){
  30. newThread(newRunnable(){
  31. @Override
  32. publicvoidrun(){
  33. System.out.println("runnabledemo:"+fibc(20));
  34. }
  35. }).start();
  36. }
  37. /**
  38. *其中Runnable实现的是voidrun()方法,无返回值;Callable实现的是V
  39. *call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下
  40. *,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
  41. */
  42. staticvoidfutureDemo(){
  43. try{
  44. /**
  45. *提交runnable则没有返回值,future没有数据
  46. */
  47. Future<?>result=mExecutor.submit(newRunnable(){
  48. @Override
  49. publicvoidrun(){
  50. fibc(20);
  51. }
  52. });
  53. System.out.println("futureresultfromrunnable:"+result.get());
  54. /**
  55. *提交Callable,有返回值,future中能够获取返回值
  56. */
  57. Future<Integer>result2=mExecutor.submit(newCallable<Integer>(){
  58. @Override
  59. publicIntegercall()throwsException{
  60. returnfibc(20);
  61. }
  62. });
  63. System.out
  64. .println("futureresultfromcallable:"+result2.get());
  65. /**
  66. *FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,
  67. *另外它还可以包装Runnable(实际上会转换为Callable)和Callable
  68. *<V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
  69. *,并且还可以通过vget()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
  70. */
  71. FutureTask<Integer>futureTask=newFutureTask<Integer>(
  72. newCallable<Integer>(){
  73. @Override
  74. publicIntegercall()throwsException{
  75. returnfibc(20);
  76. }
  77. });
  78. //提交futureTask
  79. mExecutor.submit(futureTask);
  80. System.out.println("futureresultfromfutureTask:"
  81. +futureTask.get());
  82. }catch(InterruptedExceptione){
  83. e.printStackTrace();
  84. }catch(ExecutionExceptione){
  85. e.printStackTrace();
  86. }
  87. }
  88. /**
  89. *效率底下的斐波那契数列,耗时的操作
  90. *
  91. *@paramnum
  92. *@return
  93. */
  94. staticintfibc(intnum){
  95. if(num==0){
  96. return0;
  97. }
  98. if(num==1){
  99. return1;
  100. }
  101. returnfibc(num-1)+fibc(num-2);
  102. }
  103. }

输出结果


分享到:
评论

相关推荐

    Java使用Callable和Future创建线程操作示例

    Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作技巧与注意事项。 首先,Java 5开始,Java提供了...

    Android(Java)之多线程结果返回——Future 、FutureTask、Callable、Runnable

    `Future`、`FutureTask`、`Callable`和`Runnable`是Java并发编程中的核心接口和类,它们在Android开发中同样有着广泛的应用。下面将详细介绍这些概念以及它们如何协同工作。 1. `Runnable`: 这是Java中最基础的多...

    【Java】Callable创建线程用到的适配器模式(csdn)————程序.pdf

    2. 创建FutureTask实例:FutureTask是Java并发包(java.util.concurrent)中的一个类,它是一个可以被取消的任务,同时也是一个实现了Runnable接口的Future。FutureTask提供了对Callable结果的访问和管理,包括获取...

    java多线程返回值使用示例(callable与futuretask)

    为了解决这个问题,Java提供了`Callable`接口和`FutureTask`类,它们是实现多线程返回值的关键工具。 `Callable`接口类似于`Runnable`,但比它功能更强大。`Callable`接口中的`call()`方法可以返回一个结果,并且...

    java多线程编程同步器Future和FutureTask解析及代码示例

    在Java并发编程中,通常我们会使用`ExecutorService`来提交任务,而`Future`和`FutureTask`就是与这些任务交互的关键。 首先,`Future`是一个接口,它提供了一种机制来检查异步计算是否完成,以及在计算完成后获取...

    浅谈在Java中使用Callable、Future进行并行编程

    Callable接口与Runnable接口类似,但它具有一个泛型方法`call()`,该方法在执行时会返回一个结果,并可能抛出异常。Callable接口的定义如下: ```java public interface Callable&lt;V&gt; { V call() throws Exception;...

    Java多线程Callable接口实现代码示例

    Java 多线程 Callable 接口实现代码示例 Java 多线程编程中,创建线程有多种方式,其中一种便是实现 Callable 接口。Callable 接口是一个函数式接口,定义了一个 call 方法,该方法可以抛出异常并返回结果。与 ...

    Java FutureTask类使用案例解析

    FutureTask类的内部包含一个Callable,并且可以接受Callable和Runnable作为构造函数,例如: ```java public FutureTask(Callable&lt;V&gt; callable) { if (callable == null) throw new NullPointerException(); this...

    Java多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask详解

    在Java多线程编程中,CyclicBarrier、Callable、Future和FutureTask是四个重要的组件,它们各自提供了不同的功能,帮助开发者更好地管理和协调并发任务。接下来,我们将深入探讨这些组件的特性和使用方法。 首先,...

    FutureTask学习

    总之,`FutureTask`是Java并发编程中用于异步计算的一个强大工具,它结合了`Runnable`和`Callable`的优点,提供了任务执行状态的检查以及结果的获取。理解和熟练使用`FutureTask`对于编写高效并发程序至关重要。在...

    Java concurrency线程池之Callable和Future_动力节点Java学院整理

    今天,我们将详细介绍Java concurrency线程池之Callable和Future,这两个组件在Java并发编程中扮演着重要的角色。 Callable Callable是一个接口,它只包含一个call()方法。Callable是一个返回结果并且可能抛出异常...

    Java入门基础.pdf

    * Java中的Runnable、Callable、Future、FutureTask的区别与示例 * Java程序死锁问题原理及解决方案 * 线程锁技术 * 定时器、互斥、同步通信技术 * 多个线程之间共享数据的方式探討 * 使用JDK5中同步技术的3个面试题...

    java面试精华14

    本文将深入探讨如何利用Java提供的`Runnable`与`Callable`接口配合`Future`或`FutureTask`来实现这一功能。 #### 一、基础知识回顾 在开始之前,我们先简要回顾一下`Runnable`和`Callable`这两个接口的基本概念: ...

    揭密FutureTask.docx

    在Java并发编程中,FutureTask扮演着至关重要的角色,它是实现异步计算的关键组件。本文将深入探讨FutureTask的原理和用法,帮助开发者更好地理解和利用这个强大的工具。 一、Future接口与FutureTask概述 Future...

    Java中实现线程的三种方式及对比_动力节点Java学院整理

    Java 中创建线程主要有三种方式:继承 Thread 类创建线程类、通过 Runnable 接口创建线程类、通过 Callable 和 Future 创建线程。 继承 Thread 类创建线程类 继承 Thread 类创建线程类是 Java 中最基本的线程创建...

    java长时间运行任务式

    在Java编程中,"长时间运行任务式...在压缩包文件`jobTask2`中,可能包含了示例代码或教程,用于演示如何在Java中实现多线程任务式处理。通过学习和实践这些内容,开发者可以深入理解并掌握Java多线程编程的核心技术。

    Equ中多线程实现方式.rar

    在IT行业中,多线程是程序设计中的一个重要概念,特别是在Java这种支持多线程操作的编程语言中。标题“Equ中多线程实现方式.rar”表明这是一个关于在Java环境中使用多线程进行路径规划的实践案例。从描述中反复提到...

    future.zip

    在Java中,`FutureTask`是`Future`的一个常见实现,它同时实现了`Runnable`接口,因此可以被`ExecutorService`提交执行。此外,`ExecutorService`的一些submit()方法会返回实现了`Future`接口的对象,如`Future...

    31 凭票取餐—Future模式详解.pdf

    示例代码中,创建了一个`FutureTask&lt;String&gt; cookTask`,它的构造函数接收一个Callable对象,模拟做饭的过程。当调用`cookTask.get()`时,如果任务已完成,则返回结果;否则,主线程会被阻塞,直到任务完成。在这个...

    多线程执行完后主程序再执行(包括需要子线程返回结果)

    这通常涉及到Java并发框架中的`Future`和`FutureTask`类。 `Future`接口在`java.util.concurrent`包中,它代表一个异步计算的结果。通过`Future`,我们可以检查计算是否完成,取消计算,甚至获取计算的结果。但是,...

Global site tag (gtag.js) - Google Analytics