同步调用,异步回调和 Future 模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同步调用,异步回调和 Future 模式相关的知识,希望对你有一定的参考价值。
目标通过与方法的同步调用,异步回调比较,理解 Future 模式
三者的不同
让我们先来明确一下同步与异步的不同。我们这里所说的同步和异步,仅局限在方法的同步调用和异步回调中。即,同步指的是调用一个方法,调用方要等待该方法所执行的任务完全执行完毕,然后控制权回到调用方;异步指的是调用一个方法,调用方不等该方法执行的任务完毕就返回,当任务执行完毕时会自动执行调用方传入的一块代码。
同步调用
void runTask {
doTask1()
doTask2()
}
同步调用,执行完 doTask1 在执行 doTask2
异步回调
doTask1(new Callback() {
void call() {
doTask3()
}
});
doTask2();
异步回调,会同时执行 doTask1 和 doTask2, 在执行完 doTask1 后执行 doTask3
Future 模式
Future future = doTask1();
doTask2();
doTask3();
Result result = future.get();
我们可以看到,Future 模式中,一个任务的启动和获取结果分成了两部分,启动执行是异步的,调用后立马返回,调用者可以继续做其他的任务,而等到其他任务做完,再获取Future的结果,此时调用 get 时是同步的,也就是说如果 doTask1 如果还没有做完,等它做完。
适用情景
我们根据前面的例子可以看出,同步调用适合执行耗时短的任务,异步回调适合执行耗时长的任务,而且调用它之后调用的任务没什么关系。
Future 则适合执行长得任务,而且它的结果可能与调用后执行的任务有关系。比如,在烧水的过程中洗刷水壶,最后两者都完了才能泡茶。
Future模式的 Java 实现
Java 的并发库实现了 Future 模式,它定义了 Future 接口:
public interface Future<V> {
boolean cancel(boolean var1);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}
它未来将会产生我们所需要的结果。
我们通过它取消任务的执行,判断是否取消和是否完成,获取结果。
Java 库还实现了一个 FutureTask, 它实现了 RunnableFuture(它继承了 Runnable 和 Future)。于是我们就可以用 Executor 来执行这个任务了。
FutureTask<String> futureTask = new FutureTask<>(new Runnable() {
@Override
public void run() {
}
}, "hello");
Executors.newSingleThreadExecutor().execute(futureTask);
... 其他任务
try {
String result = futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
总结
- 同步调用,调用方掌握控制权
- 异步回调,调用方放权,从而可以实现并行处理任务
- Future 模式,则是控制权和平行处理的折中
以上是关于同步调用,异步回调和 Future 模式的主要内容,如果未能解决你的问题,请参考以下文章
进阶学习5:JavaScript异步编程——同步模式异步模式调用栈工作线程消息队列事件循环回调函数
C++ std::future与promise(异步回调异步调用)