【使用Future以异步方式执行长时间的操作】
通过上面的例子,我们知道Future接口提供了方法来检测异步计算是否已经结束,等待异步操作结束,以及获取计算的结果。
但是这些特性还不足以让你编写简洁的并发代码。比如,我们很难表述Future结果之间的依赖性;从文字描述上这很简单,“当长时间计算任务完成时,请将该计算的结果通知到另一个长时间运行的计算任务,这两个计算任务都完成后,将计算的结果与另一个查询操作结果合并”。
在Future中触发那些潜在的耗时的操作把调用程序化交易 接口 代码,线程解放出来,让它能继续执行其他有价值的工作,不再需要呆呆的等待耗时的操作完成。
Stream和CompletableFuture的设计都遵循了类似的模式:它们都使用了Lambda表达式以及流水线的思想。
Future接口的局限性
打个比方,你可以把它想象成这样的场景:你拿了一袋子衣服到干洗店洗。干洗店的员工会给你张发票,告诉你什么时候你的衣服会洗好。衣服干洗的你可以去做其他的事情。
将两个异步计算合并为一个——这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果等待Future集合中的所有任务都完成。仅等待Future集合中最快结束的任务完成,并返回它的结果。通过编程方式完成一个Future任务的执行。应对Future的完成事件。
你能想象这种场景存在怎样的问题吗?如果该长时间运行的操作永远远不返回了会怎样?为了处理这种可能性,虽然Future提供了一个无需任何参数的get方法,我们还是推荐大家使用重载版本的get方法,它接受一个超时的参数,通过它,你可以定义你的程序化交易 接口 代码,线程等待Future结果的最长时间,而不是一直等待下去。
与此相反,如果你的意是实现并发,而非并行,或者你的主要目标是在同一个CPU上执行几个松耦合的任务,充分利用CPU的核,让其足够忙碌,从而最大化程序的吞吐量,那么你其实真正想做的是避免因为等待远程服务的返回,或者对数据库的查询,而阻塞程序化交易 接口 代码,线程的执行,浪费宝贵的计算资源,因为这种等待的时间很可能相当长。
Future接口,尤其是它的新版实现CompletableFuture,是处理这种情况的利器.
这种编程方式让你的程序化交易 接口 代码,线程可以在ExecutorService以并发方式调用另一个程序化交易 接口 代码,线程执行耗时操作的去执行一些其他的任务。
Future接口在Java5中被引入,设计初衷是对将来某个时刻会发生的结果进行建模。它建模了一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。
Future接口
Future的另一个优点是它比更底层的Thread更易用。要使用Future,通常你只需要将耗时的操作封装在一个Callable对象中,再将它提交给ExecutorService,就OK了。
如果你已经运行到没有异步操作的结果就无法继续任何有意义的工作时,可以调用它的get方法去获取操作的结果。
使用Future以异步的方式执行一个耗时的操作
来看下例子
import java.util.concurrent.*;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2021/4/5 9:47
* @mark: show me the code , change the world
*/
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future future = executorService.submit(() -> {
try {
TimeUnit.SECONDS.sleep(2);
return 'I'm OK ';
} catch (InterruptedException e) {
return 'I'm Error ';
}
});
while(!future.isDone()){
Thread.sleep(10);
}
// 超时时间的阻塞
// future.get(10,TimeUnit.SECONDS);
// 调用get 阻塞
System.out.println(future.get());
executorService.shutdown();
}
}
这些场景体现了多任务程序设计的另一面。我们前面学习的分支/合并框架以及并行流是实现并行处理的宝贵工具;它们将一个操作分为多个子操作,在多个不同的核、CPU甚至是机器上并行地执行这些子操作。
并行VS并发
如果操作已经完成,该方法会里立刻返回操作的结果,否则它会阻塞你的程序化交易 接口 代码,线程,直到操作完成,返回相应的结果。
使用Future中提供的方法完成这样的操作又是另外一回事。这也是我们需要更具描述能力的特性的原因,比如下面这些。
文章为作者独立观点,不代表股票交易接口观点