1.概述
在本文中,我们将了解Future。自Java 1.5以来一直存在的接口,在处理异步调用和并发处理时非常有用。
2.创建Future
简单地说,Future类表示异步计算的未来结果 - 这个结果最终将在处理完成后出现在Future中。
让我们看看如何编写创建和返回Future实例的方法。
Future接口是长时间运行方法异步处理的理想选择。这使我们能够在等待Future封装的任务完成时执行一些其他事情。
利用Future的异步性质的操作示例如下:
- 计算密集型过程(数学和科学计算)
- 操纵大数据结构(大数据)
- 远程方法调用(下载文件,抓取HTML,Web服务)。
2.1 用FutureTask实现Future
对于我们的示例,我们将创建一个非常简单的类来计算Integer的平方。这绝对不属于“长期运行”方法类别,但是我们将对它进行一次Thread.sleep()调用以使其持续1秒钟完成:
public class SquareCalculator {
private ExecutorService executor = Executors.newSingleThreadExecutor();
public Future<Integer> calculate(Integer input) {
return executor.submit(() -> {
Thread.sleep(1000);
return input * input;
});
}
}
实际执行计算的代码位包含在call()方法中,作为lambda表达式提供。正如你所看到的,除了之前提到的sleep()调用之外没有什么特别之处。
当我们将注意力转向Callable 和ExecutorService的使用时,它会变得更有趣。
Callable是一个接口,表示返回结果并具有单个call()方法的任务。在这里,我们使用lambda表达式创建了它的实例。
创建一个Callable实例并没有把我们带到任何地方,我们仍然必须将这个实例传递给一个执行器,该执行器将负责在一个新线程中启动该任务并返回有价值的Future对象。这就是ExecutorService的用武之地。
我们可以通过几种方式获得ExecutorService实例,其中大部分都是由实用程序类Executors的静态工厂方法提供的。在这个例子中,我们使用了基本的newSingleThreadExecutor(),它为我们提供了一次能够处理单个线程的ExecutorService。
一旦我们有了一个ExecutorService对象,我们只需要调用submit(&