springboot2.0 如何异步操作,@Async失效,无法进入异步
springboot异步操作可以使用@EnableAsync和@Async两个注解,本质就是多线程和动态代理。
一、配置一个线程池
@Configuration
@EnableAsync//开启异步
public class ThreadPoolConfig {
@Bean("logThread")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(4);
// 设置最大线程数
executor.setMaxPoolSize(8);
// 设置队列容量
executor.setQueueCapacity(100);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("home.bus.logThread-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
二、异步操作
比如有一个日志服务需要异步入库
@Service
public class LogServiceImpl implements LogService { @Resource
SysLogRepository sysLogRepository; private Logger logger = LoggerFactory.getLogger(LogServiceImpl.class); @Override
@Async("logThread")//对应线程池里的bean
public void writeLog(SysLog sysLog)
{
long start = System.currentTimeMillis();
try {
Thread.sleep(3000);//为了测试加入,绝对不是为了以后给客户优化性能加入
}catch (Exception e)
{
e.printStackTrace();
}
sysLogRepository.save(sysLog);
long end = System.currentTimeMillis();
logger.info("异步日志入库完成,耗时:"+(end-start)+"毫秒,入库内容:"+sysLog);
} }
这里有一个小坑,writeLog函数不能由本类内其他函数调用,必须是外部使用者调用,如果内部函数调用会出现代理绕过的问题,从而无法执行异步,不会出错,会变成同步操作。看起来就是@Async失效的状态。
例如:
@Service
public class LogServiceImpl implements LogService { @Resource
SysLogRepository sysLogRepository; private Logger logger = LoggerFactory.getLogger(LogServiceImpl.class); @Override
@Async("logThread")//对应线程池里的bean
public void writeLog(SysLog sysLog)
{
long start = System.currentTimeMillis();
try {
Thread.sleep(3000);
}catch (Exception e)
{
e.printStackTrace();
}
sysLogRepository.save(sysLog);
long end = System.currentTimeMillis();
logger.info("异步日志入库完成,耗时:"+(end-start)+"毫秒,入库内容:"+sysLog);
} public void doSysLog(String action,String event)
{
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
SysLog sysLog = new SysLog();
sysLog.setAction(action);
sysLog.setEvent(event);
sysLog.setHost(NetworkUtils.getIpAddress(request));
sysLog.setUserName((String)request.getSession().getAttribute("userName"));
sysLog.setInsertTime(LocalDateTime.now()); wirteLog(sysLog);//这里不会进入异步
} }
使用doSyslog调用异步函数wirteLog,最终会是一个同步方法。为什么不直接在doSysLog函数加上异步注解?因为RequestContextHolder在异步里取不到信息。
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
三、调用异步
比如登录controller,登录成功后调用异步日志入库
LoginResult loginResult = loginService.login(userName, password);
if (loginResult.isLogin()) {
map.put("userName", userName);
SysLog sysLog = LogFactory.createSysLog("登录","登录成功");
logService.writeLog(sysLog);//这里异步,完全阻塞,如果之前函数内嵌套调用,这里就阻塞了,把sleep设置大一些可以看得明显
return "/index";
} else {
map.put("msg", loginResult.getResult());
map.put("userName", userName);
return "/user/login";
}
这里SysLog 对象直接在调用层生成,也就是把doSysLog拆分成两个部分处理,logService直接调用异步方法,正常情况不会阻塞,直接就到下一步。
结果:
[home.bus.logThread-1] INFO c.h.bus.service.impl.LogServiceImpl - 异步日志入库完成,耗时:3089毫秒,入库内容:SysLog{logId=367, userName='admin', host='0:0:0:0:0:0:0:1', action='登录', event='登录成功', insertTime=2018-11-16T00:18:32.522}
springboot2.0 如何异步操作,@Async失效,无法进入异步的更多相关文章
- 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...
- 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单 async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...
- [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单 async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...
- 四、C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...
- SpringBoot2.0 基础案例(04):定时任务和异步任务的使用方式
一.定时任务 1.基本概念 按照指定时间执行的程序. 2.使用场景 数据分析 数据清理 系统服务监控 二.同步和异步 1.基本概念 同步调用 程序按照代码顺序依次执行,每一行程序都必须等待上一行程序执 ...
- C# 5.0 新特性——Async和Await使异步编程更简单
http://www.cnblogs.com/zhili/archive/2013/05/15/csharp5asyncandawait.html http://blog.zhaojie.me/201 ...
- Springboot2.0(Spring5.0)中个性化配置项目上的细节差异
在一般的项目中,如果Spring Boot提供的Sping MVC不符合要求,则可以通过一个配置类(@Configuration)加上@EnableWebMvc注解来实现完全自己控制的MVC配置.但此 ...
- springBoot2.0 配置shiro实现权限管理
一.前言 基于上一篇springBoot2.0 配置 mybatis+mybatisPlus+redis 这一篇加入shiro实现权限管理 二.shiro介绍 2.1 功能特点 Shiro 包含 10 ...
- springboot2.0+mybatis多数据源集成
最近在学springboot,把学的记录下来.主要有springboot2.0+mybatis多数据源集成,logback日志集成,springboot单元测试. 一.代码结构如下 二.pom.xml ...
随机推荐
- 180706-BigDecimal除法的精度问题
BigDecimal除法的精度问题 在使用BigDecimal的除法时,遇到一个鬼畜的问题,本以为的精度计算,结果使用返回0,当然最终发现还是自己的使用姿势不对导致的,因此记录一下,避免后面重蹈覆辙 ...
- Katalon 学习笔记(一)
工具介绍: Katalon Studio是一个能提供一整套功能来实现Web,API和Mobile的全自动测试解决方案的自动化测试平台.Katalon Studio构建于开源Selenium和App ...
- 总结获取原生JS(javascript)基本操作
var a = document.getElementByIdx_x_x("dom"); jsCopy(a);//调用清理空格的函数 var b = a.childNodes;// ...
- 一种跨平台的C++遍历目录的方法
参考了网络上各路大神的实现方法.主要使用了io.h库 #include <iostream> #include <cstring> #include <io.h> ...
- 水管工游戏:dfs(递归)
添柴网这题好想不能评测,所以不确保代码的正确性 题目描述: 这小节有点难,看不太懂可以跳过哦.最近小哼又迷上一个叫做水管工的游戏.游戏的大致规则是这样的.一块矩形土地被分为N * M的单位正方形,现在 ...
- nginx web服务器的安装使用
nginx是一个web服务器(高性能web服务器),类似于apache服务器和iis服务器,由于nginx服务器具有轻量级高并发的特点,目前nginx的使用已经超越了apache. nginx介绍:n ...
- opencv-学习笔记(2)
opencv-学习笔记(2) 这章记录了 获取像素点,改变像素点 获取图像的属性(行,列,通道数,数据类型) roi感应区 拆分以及合并图像通道 边缘扩充 opencv获取像素点,改变像素点 ---- ...
- leetcode个人题解——#22 Generate Parentheses
思路: 递归解决,如果左括号个数小于右括号或者左括号数小于总括号对数,则生成一个左括号,如果左括号数大于右括号,生成一个右括号. class Solution { public: vector< ...
- dice2win
触发交易 转0个 https://etherscan.io/tx/0x784e80167353a886183106cbe3bd15e614cafdb5d6885ccd101177aa0f937a36 ...
- 给你的WP应用加上帮助文档
背景 这算是Windows Phone编程回顾续篇, 接着给大家聊WP开发经验. 在开发了数个WP应用并发布后, 陆续收到很多反馈邮件, 其中接近一半的邮件是在问"某某功能有没有?" ...