@Async 是什么

void test() {
A();
B();
C();
}
复制代码

在没有Async的情况下,上面的方法是顺序执行的,也可以称为同步调用. B要在A执行完毕之后执行,C需要在B执行完毕之后执行,整个函数结束是在C执行完毕之后。

但是如果给B添加了@Async,执行顺序不变, 在执行完A之后,调用B,但是并不等待B完成,就执行C,C执行完毕之后,这个函数就执行完毕了.

在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。

什么时候需要添加@Async

根据业务需求,可以将暂时不需要获得处理的方法设置为@Async.

比如用户在前端点击完成了登录操作,这时候根据业务要求需要在登录成功之后进行埋点的处理.

其实埋点成功与否都不影响用户操作,这时候就可以将埋点方法设置为@Async.

个人认为此类任务通常有三个特征:

  1. 业务优先级低.
  2. 运行时间长,可能会造成卡顿.
  3. 返回结果暂时不立即处理,包括exception.

如何使用@Async

  1. 对当前Application添加@EnableAsync,当然也可以添加到Config,主要的是让Spring知道你有开启Async.
@EnableAsync
@SpringBootApplication
public class TestApplication { public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
复制代码
  1. 对当前方法添加Async
@Async
public void B() { }
复制代码
  1. 注意事项 对Static方法修饰无效! 调用与被修饰方法不能写在同一个函数中。

比如:

class Test {

    public void A() {
B(); // 这时候不会触发Async
} @Async
public void B() { } }
复制代码

所以需要拆开调用:

class Test {

    public void A() {
TestB testB = new TestB();
testB.B();
}
} class TestB {
@Async
public void B() { }
}
复制代码
  1. 返回值只能为Future或者Void, Future的使用方式.
@Async
public Future<String> asyncMethod() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
System.out.println("StartTime - " + Thread.currentThread().getName() + df.format(new Date()));
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("EndTime - " + Thread.currentThread().getName() + df.format(new Date()));
return new AsyncResult<String>("hello world!");
} @Test
public void contextLoads() {
Future<String> result1 = test.asyncMethod();
Future<String> result2 = test.asyncMethod();
Future<String> result3 = test.asyncMethod();
while (!result1.isDone() || !result2.isDone() || !result3.isDone()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
复制代码

自定义线程池

@Configuration
public class TaskConfiguration {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // 线程池创建时候初始化的线程数
executor.setMaxPoolSize(20); // 线程池最大的线程数,只有在缓冲队列满了之后,才会申请超过核心线程数的线程
executor.setQueueCapacity(200); // 缓冲任务队列的大小
executor.setKeepAliveSeconds(60); // 允许线程的空闲时间,超过会被销毁
executor.setThreadNamePrefix("custom-prefix-");// 线程的前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 对拒绝任务的处理策略 return executor;
}
} //定义之后在Async中指定
@Async("taskExecutor")
......
复制代码

由于在应用关闭的时候异步任务还在执行,导致类似 数据库连接池 这样的对象一并被 销毁了,当 异步任务 中对 数据库 进行操作就会出错。

setWaitForTasksToCompleteOnShutdown(true): 该方法用来设置 线程池关闭 的时候 等待 所有任务都完成后,再继续 销毁 其他的 Bean,这样这些 异步任务销毁 就会先于 数据库连接池对象 的销毁。 setAwaitTerminationSeconds(60): 该方法用来设置线程池中 任务的等待时间,如果超过这个时间还没有销毁就 强制销毁,以确保应用最后能够被关闭,而不是阻塞住。

SpringBoot中的异步编程的更多相关文章

  1. .Net中的异步编程总结

    一直以来很想梳理下我在开发过程中使用异步编程的心得和体会,但是由于我是APM异步编程模式的死忠,当TAP模式和TPL模式出现的时候我并未真正的去接纳这两种模式,所以导致我一直没有花太多心思去整理这两部 ...

  2. C#中的异步编程Async 和 Await

    谈到C#中的异步编程,离不开Async和Await关键字 谈到异步编程,首先我们就要明白到底什么是异步编程. 平时我们的编程一般都是同步编程,所谓同步编程的意思,和我们平时说的同时做几件事情完全不同. ...

  3. .NET中的异步编程——常见的错误和最佳实践

    在这篇文章中,我们将通过使用异步编程的一些最常见的错误来给你们一些参考. 背景 在之前的文章<.NET中的异步编程——动机和单元测试>中,我们开始分析.NET世界中的异步编程.在那篇文章中 ...

  4. javaScript中的异步编程模式

    1.事件模型 let button = document.getElementById("my-btn"); button.onclick = function(event) { ...

  5. Netty 中的异步编程 Future 和 Promise

    Netty 中大量 I/O 操作都是异步执行,本篇博文来聊聊 Netty 中的异步编程. Java Future 提供的异步模型 JDK 5 引入了 Future 模式.Future 接口是 Java ...

  6. 一文说通C#中的异步编程

    天天写,不一定就明白. 又及,前两天看了一个关于同步方法中调用异步方法的文章,里面有些概念不太正确,所以整理了这个文章.   一.同步和异步. 先说同步. 同步概念大家都很熟悉.在异步概念出来之前,我 ...

  7. 一文说通C#中的异步编程补遗

    前文写了关于C#中的异步编程.后台有无数人在讨论,很多人把异步和多线程混了. 文章在这儿:一文说通C#中的异步编程 所以,本文从体系的角度,再写一下这个异步编程.   一.C#中的异步编程演变 1. ...

  8. SpringBoot 如何实现异步编程,老鸟们都这么玩的!

    镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 首先我们来看看在Spring中为什么要使用异步编程,它能解决什么问题? 为什么要用异步框架,它解决什么问题? 在SpringBoot的日常开发中 ...

  9. promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

    * promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...

随机推荐

  1. DOM 事件机制&事件委托

    一.事件机制 事件是在编程时系统内发生的动作或者发生的事情,系统会在事件出现的时候触发某种信号并且会提供一个自动加载某种动作的机制(来自MDN).每个事件都有事件处理器(有时也叫事件监听器),也就是触 ...

  2. Java多线程_wait/notify/notifyAll方法

    关于这三个方法,我们可以查询API得到下列解释: wait():导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法或者指定的事件用完 notify( ...

  3. instanceof判断问题

    有时候我们根据instanceof来判断对象的数据类型 但是 用instanceof判断基本数据类型时 会不靠谱 例如 let str = '123' let str1 = new String(&q ...

  4. Springboot中登录后关于cookie和session拦截案例

    目录 一.前言 二.利用Cookie进行登录验证 一.前言 1.简单的登录验证可以通过Session或者Cookie实现. 2.每次登录的时候都要进数据库校验下账户名和密码,只是加了cookie 或s ...

  5. OGG复制进程延迟高,优化方法二(存在索引),SQL选择不好的索引

    https://www.cnblogs.com/lvcha001/p/13469500.html 接前序,本次场景中有索引,但是OGG复制进程使用了低效率的索引?  类似SQL使用低效索引,如何让Or ...

  6. 网站会不会因为同IP网站被K而受到惩罚

    http://www.wocaoseo.com/thread-289-1-1.html 使用虚拟主机的网站会不会因为同一个IP或同一台服务器上有其他网站作弊被处罚而受连累,也被惩罚? 复制代码 百度官 ...

  7. Qt 改变鼠标形状

    Qt 改变鼠标形状(转载) 改变鼠标形状,在绘制坐标系的时候有用到,特此记下: 1 this->setMouseTracking(true); //设置为不按下鼠标键触发moveEvent 2 ...

  8. 码云git clone报错Incorrect username or password ( access token )

    使用码云将仓库clone到本地,报错信息如下: D:\>git clone https://gitee.com/ycyzharry/helloworld.git Cloning into 'he ...

  9. row_number()分页返回结果顺序不确定

    之前通过row_number()实现分页查询时: select top [PageSize] * from ( select row_number() over (order by id desc) ...

  10. shell小技巧(3)复制文件到其他主机

    复制一个文件nfsclient.sh到主机172.18.117.162的/tmp目录下 scp -P22 /tmp/nfsclient.sh  root@172.18.117.162:/tmp -P2 ...