一、定义
1.1 什么是异步任务
说到异步任务,我们第一时间想到的是多线程,我们常说的多线程问题,一般是指线程并发问题和数据同步问题。而异步任务属于多线程编程的一个环节:主线程在继续当前任务的同时,创建一个或多个新的非阻塞线程去执行其他任务。
1.2 异步任务解决了什么问题
当主流程外需要执行1个或多个复杂计算,为了保障执行效率,可以使用异步任务。异步任务的主要作用是最大程度地使用服务器的性能,提升程序的响应速度。
1.3 业务场景
无需获取响应结果的简单异步 如:消息通知
需要响应结果的异步 如:商品信息查询
二、Future模式
2.1 Future模式的概念
我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。
2.2 Future模式的变种
Callback:任务执行结束后主动触发其他任务流程图
Promise:支持对任务结果的修改
三、Java实现异步任务的方式
3.1 怎样实现异步任务?
JDK1.5 之前——Runnable接口
在jdk1.5之前,Java仅支持通过Runnable接口创建线程。Runnable接口只有一个返回类型为void的run方法,不支持获取返回值。
public interface Runnable {
public abstract void run();
}
我们可以通过创建Thread对象来实现异步任务:
class Thread implements Runnable {
private Runnable target;
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
@Override
public void run() {
if (target != null) {
target.run();
}
}
}
@Test
public void testNewThread() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello new thread");
}
});
t1.start();
}
存在的问题:
-
Runnable接口没有返回值
-
Runnable接口不支持抛出异常
JDK1.5 ——FutureTask
为了解决获取异步任务结果的问题,JDK新增了Callable接口
public interface Callable<V> {
V call() throws Exception;
}
怎样使用Callable接口?
JDK1.5还新增了Future接口和ExecutorService,Callable接口需要与Future和ExecutorService结合使用
public interface Future<V> {
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
<T> Future<T> submit(Callable<T> task);
}
查看ThreadPoolExecutor的源码会发现,submit方法返回的Future对象实际上是一个FutureTask。
Future接口的实现——FutureTask

FutureTask实现了Future接口,为Java使用者提供了Future模式的基本功能。怎样使用FutureTask?
- FutureTask继承了Runnable接口,可结合Thread使用,也可以通过Executor的execute方法被执行
- FutureTask也继承了Future接口,可以作为ExecutorService的submit返回结果,作为获取异步任务响应的凭证
JDK1.8 ——CompletableFuture
JDK1.8 新增了CompletableFuture,它是Future接口的另一个实现类。为什么JDK新增了CompletableFuture?
它有三大功能是Future以及FutureTask所没有的:
- 异步任务回调(callback模式)
- 异步任务批处理
- 主动完成任务并设置返回值(promise模式)
3.2 FutureTask VS CompletableFuture
网友评论