Java 中为什么需要Future

226 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

这篇文章我们来说明一下Java 中的Future。

在我们的面试的时候经常会被问到Java 并发编程的事情,而在Java 并发编程中,一个很重要的知识就是如何使用多线程。在这里面,Future 却是一个非常重要的概念。

Future 的引入

首先我们需要介绍,什么是Future,为什么会有Future 的存在。

在而我们日常开发中,最常用的实现多线程的接口就是Runnable接口,也可以直接写个类来继承Thread,完成我们需要的多线程的逻辑。但是使用Runnalble有个明显的问题就是它没有返回值。当我们需要任务执行完成后给出结果的时候,如果使用上面的两种方式,我们是无法直接在代码中得到返回值的,当然也有一些其他方法可以实现,比如说通过写共享对象,通过写文件来实现。

另外还有个问题,如果使用Runnable接口中的run方法,它是无法抛出异常的,当我们想在任务的处理过程中抛出异常的时候,就无法使用Runnable接口来完成这个功能了。就算即使可以抛出异常了,因为它也没有办法获取返回值,这也导致了我们无法接收这个异常。

面对上面那两个问题,在java 中定义了Callable接口,定义如下:

public interface Callable<V> {
     V call() throws Exception;
}

在这个接口中,我们可以看到,它有返回值,同时可以抛出异常。但是我们仔细看看,就会发现这里面的问题了:

  1. 对于抛出的异常我们如何接收
  2. 对于返回值我们又如何接收(我们设想,如果每个线程都有返回值,如果我们需要在代码中得到返回值,那么我们就需要等待子线程执行完毕才可以获取并处理这个返回值。但是这样依赖,这个多线程就会变成同步的了所谓的“并发编程”也就没有意义了。)

这个时候我们就需要引入Future了。Future同样也是Java 中的一个接口,它类似于一个容器,用来保存Callable的返回结果。

同时,在使用Future 的时候,我们需要配合线程池来使用,这样就可以更好地行使Future的功能。

首先我们可以把子任务放入线程池,之后就可以直接返回了。然后我们就能继续进行其他事情的处理,这不会耽误线程的执行。当其他事情处理完成,我们就可以再调用Futureget方法来获取结果。

另外,Future也可以控制执行中的线程来进行对应的操作。

总结

这篇文章主要是介绍引入Future的意义。希望读者好好理解。