美文网首页
Java并发 - Future模式

Java并发 - Future模式

作者: 齐晋 | 来源:发表于2018-12-16 18:02 被阅读39次

标签:原创 Java 并发

更多Java并发实战内容,请参考Java并发 - 并发编程实战

理解Future

关于Future模式的教程,网上很多,这里就不做详细介绍了。可参考的文章如:

Future关键点

这里重点对Future模式的几个关键点做下总结和扩展。

为什么需要Future

其实在多线程中,Future的主要作用在于获取执行结果或执行状态。

当从主线程中启动一个子线程,那么子线程就像一匹脱缰的野马,很难知道什么时候执行完成,什么时候结束。

如果主线程依赖子线程的结果,由于不知道子线程的执行状态,就可能需要使用彻底理解Java的Future模式所讲的join方式去等待子线程返回结果。这种情况下,主线程会被阻塞,其实跟串行没有什么区别。因此,这种同步等待的方式是不可取的。

Future模式就是为了实现主线程和子线程同时进行工作,在需要的时候,主线程才去等待子线程结果这种功能。

就像两个人一起算账,A(假设是主线程)算一部分,B(假设是子线程)算一部分,两个人同时计算自己的部分。当A算完以后,再通过Future.get()方法来获取B计算的结果,最后进行累加。这时,如果B已经算完了,get()方法直接返回结果。如果B还没算完,就等待B算完。

怎样使用Future

java concurrent包中的ThreadPoolExecutor中有个sumbmit()方法,返回的就是Future对象:

public Future<?> submit(Runnable task);
public <T> Future<T> submit(Runnable task, T result);
public <T> Future<T> submit(Callable<T> task);

Future有什么缺点?
Future有个大缺点就是没有办法异步化。也就是说,当子线程的处理结果需要进一步处理时,主线程需要调用get()方法。但是get()方法什么时候调用?这是个很难选择的时间点:可以任何时候调用!

如果立即调用,get()方法会阻塞主线程,这又成串行执行了!
如果最后调用,子线程可能早就执行完了,还得保存结果,等待主线程处理!
计算机程序最浪费时间的操作就是"等待"

为了避免这种等待,最好使用回调的方式。举个例子:

主线程发起一个子线程去做一个事情后,继续执行。在主线程不依赖子线程结果的情况下,子线程处理完成后,将处理结果教给另一个线程去做记录。
这样,所有的线程都不会等待,还完成了各自的工作。

鉴于JDK Future的缺点,并且解决速度很慢,Guava封装了增强版的Future,供开发者使用

Guava Future

guava对Future的增强可参考文章:

总结起来如下:

  • JDK的Future,guava对应的增强版本是ListenableFuture
  • ListenableFuture增加了void addListener(Runnable listener, Executor executor);方法,可以让子线程在结束的时候,主动调用listener对象,达到异步处理多结果
  • JDK的FutureTask,guava对应的增强版本是ListenableFutureTask
  • JDK的线程池返回的结果只有Future。所以为了支持返回ListenableFuture,guava又封装了一系列的线程池,如:
    • ListeningExecutorService对应JDK的ExecutorService
    • MoreExecutors对应JDK的Executors
  • 还提供了能在调用线程中执行回调的ExecutorService,即 DirectExecutor

guava增强的使用方法与JDK原生的大同小异

怎么使用guava Future?
从上得知,要使用guava的增强,需要使用guava线程池。guava在MoreExecutors中提供了诸多方法,将JDK原生线程池,封装成适合guava体系的线程池,如:

public static ListeningExecutorService listeningDecorator(ExecutorService delegate);

public static ListeningScheduledExecutorService listeningDecorator(
      ScheduledExecutorService delegate);

JDK8 CompletableFuture

除了guava扩展了Future,Netty等高性能框架也扩展了Future,可见JDK原生的Future是多么不好用,牛B的程序员已经忍无可忍了。

JDK做为正统的Java类库,是不是该做点什么。

终于在JDK8的时候,千呼万唤,出现了CompletableFuture:

关于CompletableFuture的文章可参考:

相关文章

网友评论

      本文标题:Java并发 - Future模式

      本文链接:https://www.haomeiwen.com/subject/qpyxkqtx.html