文章目录
- 概念
- 实现方式
- Thread
- 说明
- Async注解
- 说明
- 线程池
- CompletableFuture(Future及FutureTask)
- 创建CompletableFuture
- 异步执行
- 消息队列
概念
- 异步执行模式:是指语句在异步执行模式下,各语句执行结束的顺序与语句执行开始的顺序并不一定相同。
- 例如 查询操作,客户机上的应用程序在向服务器发出了查 询操作的指令后,将立刻执行查询语句指令的下一条 语句,而不需要等到服务器将查询结果返回客户机端。异步执行方式使应用程序能摆 脱单个任务的牵制,提高了灵活性和应用程序的执行 效率。但异步执行模式也存在一些问题,如它增加了编程的复杂性,特别是编写互用性(interoperable)要求较高 的程序。
- 虽然使用异步执行模式在编程序时十分复杂,但可以实现多任务并行执行,使执行的效率大大提高。
这里总结下自己所了解及使用过的可以实现异步执行的几种方式:
实现方式
Thread
直接new Thread()执行方法。
public static void main(String[] args) throws InterruptedException {
System.out.println("main开始");
Thread thread = new Thread(() -> {
System.out.println("子线程执行");
});
thread.start();
Thread.sleep(1000);
System.out.println("main结束");
}
说明
可以实现异步,但是这种实现会有问题:
- 每次new Thread() 都会创建新的对象,开销较大,无法复用增加垃圾回收的负担。
- 每个new Thread() 都是独立的个体,无法有效的管控,无限制创建相互竞争,可能导致oom或者核心业务线程阻塞。
- 缺乏更多功能,如定时执行、定期执行、线程中断。
Async注解
以spring boot为例,@Async简单使用方法:
- 启动类中增加@EnableAsync。
- 方法上面加上@Async。
说明
- 在方法上使用该@Async注解,申明该方法是一个异步任务;
- 在类上面使用该@Async注解,申明该类中的所有方法都是异步任务;
- 使用此注解的方法的类对象,必须是spring管理下的bean对象;
- 要想使用异步任务,需要在主类上开启异步配置,即,配置上@EnableAsync注解;
- 在目标方法(说到目标方法,说到 target,说明存在一个代理对象)的签名中,入参是任何类型都支持的。但是,返回类型被限制为 void 或者 Future。所以,异步方法的返回值只能有两种:void 或者 Future。
- @Async自定义线程池:
查看该注解可以看到只有一个参数value
这个value属性就是用来传线程池的bean名称的,用于指定线程池。如果@Async不指定任何value值,那么Spring 使用默认的线程池/执行器 去执行这些异步方法,这个默认的执行器就是:SimpleAsyncTaskExecutor。 - Async失效的场景,可以查看之前的博客:@Async不生效原因
线程池
可以在代码里面显式的创建线程,比如第一种方式,但是如果线程多的话会消耗系统资源,效率
低下并且还会降低系统稳定性。可以看到阿里巴巴编码规范提示:
所以我们使用线程池提前创建好一些固定的线程数一直在运行状态实现复用,从而可以减少就绪到运行状态的切换。优势是:(不用记知道即可)
- 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
- 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
- 提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行。
代码如下:
CompletableFuture(Future及FutureTask)
Future及FutureTask就不说了,直接说完美形态:CompletableFuture,JDK8中新增加了一个包含50个方法左右的类CompletableFuture,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。
创建CompletableFuture
// 无返回结果
CompletableFuture<String> completableFuture = new CompletableFuture<>();
// 已知返回结果
CompletableFuture<String> completableFuture = new CompletableFuture<>("result");
// 已知返回结果(底层其实也是带参数的构造器赋值)
CompletableFuture<String> completedFuture = CompletableFuture.completedFuture("result");
异步执行
- runAsync():runAsync()方法的参数是Runnable接口,这是一个函数式接口,不允许返回值。当需要异步操作且不关心返回结果的时候可以使用runAsync()方法。
- supplyAsync():supplyAsync()方法的参数是Supplier供给型接口(无参有返回值),这也是一个函数式接口,U是返回结果值的类型。当需要异步操作且关心返回结果的时候,可以使用supplyAsync()方法。
消息队列
基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统 。