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失效,无法进入异步的更多相关文章

  1. 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...

  2. 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单

    本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单  async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...

  3. [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单

    本专题概要: 引言 同步代码存在的问题 传统的异步编程改善程序的响应 C# 5.0 提供的async和await使异步编程更简单  async和await关键字剖析 小结 一.引言 在之前的C#基础知 ...

  4. 四、C# 5.0 新特性——Async和Await使异步编程更简单

    一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...

  5. SpringBoot2.0 基础案例(04):定时任务和异步任务的使用方式

    一.定时任务 1.基本概念 按照指定时间执行的程序. 2.使用场景 数据分析 数据清理 系统服务监控 二.同步和异步 1.基本概念 同步调用 程序按照代码顺序依次执行,每一行程序都必须等待上一行程序执 ...

  6. C# 5.0 新特性——Async和Await使异步编程更简单

    http://www.cnblogs.com/zhili/archive/2013/05/15/csharp5asyncandawait.html http://blog.zhaojie.me/201 ...

  7. Springboot2.0(Spring5.0)中个性化配置项目上的细节差异

    在一般的项目中,如果Spring Boot提供的Sping MVC不符合要求,则可以通过一个配置类(@Configuration)加上@EnableWebMvc注解来实现完全自己控制的MVC配置.但此 ...

  8. springBoot2.0 配置shiro实现权限管理

    一.前言 基于上一篇springBoot2.0 配置 mybatis+mybatisPlus+redis 这一篇加入shiro实现权限管理 二.shiro介绍 2.1 功能特点 Shiro 包含 10 ...

  9. springboot2.0+mybatis多数据源集成

    最近在学springboot,把学的记录下来.主要有springboot2.0+mybatis多数据源集成,logback日志集成,springboot单元测试. 一.代码结构如下 二.pom.xml ...

随机推荐

  1. day 4 飞机大战-面向对象

    1.飞机类 #-*- coding:utf-8 -*- import pygame import time from pygame.locals import * class HeroPlane(ob ...

  2. EF SQLite的Like语句,生成为CHARINDEX的解决办法

    在使用EF SQLite的时候发现Like语句不能完全查询出来,看了下生成的SQL语句类似于这种 (CHARINDEX(@p__linq__2, [Extent1].[LeagueName])) &g ...

  3. unity3d 角色头顶信息3D&2D遮挡解决方案(一)

    先上效果图,只凭文字描述,脑补应该有些困难- - 如图:有三个角色(我们暂且从左到右叫它们A.B.C),一个2D UI(中间动作选择的框框),一个cube(右边的方块) cube挡住了角色C的头顶信息 ...

  4. Linux命令应用大词典-第5章 显示文本和文件内容

    5.1 cat:显示文本文件 5.2 more:分页显示文本文件 5.3 less:回卷显示文本文件 5.4 head:显示指定文件前若干行 5.5 tail:查看文件末尾数据 5.6 nl:显示文件 ...

  5. 博客更换至 www.zhaoch.top

    博客更换至 www.zhaoch.top 随手拷了一些链接 http://www.zhaoch.top/操作系统/linux/常用命令备忘.html http://www.zhaoch.top/操作系 ...

  6. js for循环实例

    1.求1-100的寄数和? //2.奇数求和 var ppt=0 for(var i=1;i<=100;i+=2){ ppt+=i } 2.求1-100的偶数和 var num=0 for(va ...

  7. 一键部署 Docker Datacenter ---简化docker数据中心安装步骤

    DDC 简介 2016年2月下旬,Docker发布了企业级容器管理和服务部署的整体解决方案平台-Docker Datacenter,简称DDC.DDC 有三个组件构成:1. Docker Univer ...

  8. 八:The YARN Timeline Server

    一.Overview 介绍     yarn timeline server用于存储和检查应用程序过去和现在的信息(比如job history server).有两个功能: 1.Persisting ...

  9. 【IdentityServer4文档】- 整体情况

    整体概况 大多数现代应用程序看起来或多或少像这样: 最常见的交互是: 浏览器与 Web 应用程序进行通信 Web 应用程序与 Web API 进行通信(有时是Web应用程序自己发起,有时代表用户发起) ...

  10. lintcode-187-加油站

    187-加油站 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油gas[i],并且从第_i_个加油站前往第_i_+1个加油站需要消耗汽油cost[i]. 你有一辆油箱容量无限大的汽车,现在要从 ...