@Async如何使用

  • 异步的方法上加上@Async异步注解
  • 启动类中需要加上@EnableAsync才有效

    使用时类似于下列函数:
new Thread(()-> System.out.println("hello world !"))

@Async线程池

  • 默认线程池

    无论重复多少次,都默认8个左右的线程在跑

    异步线程:task-1执行成功

    异步线程:task-2执行成功

    异步线程:task-3执行成功

    异步线程:task-4执行成功

    异步线程:task-5执行成功

    异步线程:task-6执行成功

    异步线程:task-7执行成功

    异步线程:task-1执行成功

    异步线程:task-2执行成功

    异步线程:task-8执行成功

    异步线程:task-3执行成功

    异步线程:task-8执行成功

    异步线程:task-6执行成功

    异步线程:task-8执行成功

    异步线程:task-5执行成功

    异步线程:task-3执行成功

    异步线程:task-2执行成功

    异步线程:task-1执行成功
  • 自定义线程池配置
/**
* 为Async配置自定义线程池
* 可存放的最多线程数为:MAX_POOL_SIZE+QUEUE_CAPACITY,同时进入线程池的数量超过这个就会报错
* 线程名称最多为MAX_POOL_SIZE个
*/
@Configuration
public class MyTaskExecutorConfig implements AsyncConfigurer { /**
* 设置ThreadPoolExecutor的核心池大小。
*/
private static final int CORE_POOL_SIZE = 2;
/**
* 设置ThreadPoolExecutor的最大池大小。
*/
private static final int MAX_POOL_SIZE = 3;
/**
* 设置ThreadPoolExecutor的BlockingQueue的容量。
*/
private static final int QUEUE_CAPACITY = 5; /**
* 配置类实现AsyncConfigurer接口并重写getAsyncExcutor方法,并返回一个ThreadPoolTaskExevutor
* 这样我们就获得了一个基于线程池的TaskExecutor
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
taskExecutor.initialize();
return taskExecutor;
}
}

异步线程:ThreadPoolTaskExecutor-2执行成功

异步线程:ThreadPoolTaskExecutor-1执行成功

异步线程:ThreadPoolTaskExecutor-3执行成功

异步线程:ThreadPoolTaskExecutor-1执行成功

异步线程:ThreadPoolTaskExecutor-3执行成功

异步线程:ThreadPoolTaskExecutor-2执行成功

异步线程:ThreadPoolTaskExecutor-1执行成功

异步线程:ThreadPoolTaskExecutor-3执行成功

@Async和@Controller同时使用存在异常

AbstractHandlerMethodMapping初始bean时,在afterPropertiesSet方法中initHandlerMethods()关联我们的SpringMVCBean

// 类型判断
if (beanType != null && isHandler(beanType)) {
// url处理
detectHandlerMethods(beanName);
} // Controller和RequestMapping注解判断
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

a、@Controller不使用@Async注解时

@RestController
@Slf4j
public class MemberServiceImpl1 { @GetMapping("/addUser1")
public String addUser() {
log.info(">>>流程1");
log.info(">>>流程2");
return "success";
}
}

b、@Controller使用@Async注解,但不继承接口时,异步失效

@RestController
@Slf4j
public class MemberServiceImpl3 { @GetMapping("/addUser3")
public String addUser() {
log.info(">>>流程1");
addUserLog();
log.info(">>>流程3");
return "success";
} @Async()
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) { }
log.info(">>>流程2");
return "success";
}
}



c、@Controller使用@Async注解,同时继承接口

@RestController
@Slf4j
public class MemberServiceImpl4 implements MemberService { @Override
@GetMapping("/addUser4")
public String addUser() {
log.info(">>>流程1");
addUserLog();
log.info(">>>流程3");
return "success";
} @Async()
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) { }
log.info(">>>流程2");
return "success";
}
}



@Async使用建议

  • a、异步执行的建议单独开启一个类实现,或者从容器中直接获取到该代理类后执行
/**
* 异步代码写到别的地方,不要和Controller注解同时使用
*/
@RestController
@Slf4j
public class ResolveServiceImpl { @Autowired
private MemberServiceManage memberServiceManage; @GetMapping("/resolve2")
public String addUser() {
log.info(">>>流程1");
memberServiceManage.addUserLog();
log.info(">>>流程3");
return "success";
}
}
@Component
@Slf4j
public class MemberServiceManage {
@Async
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) { }
log.info(">>>流程2");
return "success";
}
}
/**
* 使用SpringUtils获得bean后调用,不要使用this操作
*/
@RestController
@Slf4j
public class ResolveServiceImpl { @GetMapping("/resolve1")
public String addUser() {
log.info(">>>流程1");
//把直接调用改为从容器中取一次
ResolveServiceImpl bean = SpringUtils.getBean(ResolveServiceImpl.class);
bean.addUserLog();
log.info(">>>流程3");
return "success";
} @Async()
public String addUserLog() {
try {
Thread.sleep(1000);
} catch (Exception e) { }
log.info(">>>流程2");
return "success";
}
}
  • b、异步的方法上不要加static,加了static就不走AOP了

最新文章

  1. SQL Server 自定义聚合函数
  2. Rest API 开发 学习笔记(转)
  3. sql server 导出表结构
  4. Android实现全屏的三种方式
  5. Android APP开发笔记
  6. Azure HDInsight与Hadoop周边系统集成
  7. MSSQLSERVER数据库- 杂记
  8. BZOJ 1072 [SCOI2007]排列perm
  9. Rule Or WorkFlow
  10. BigDecimal 专题
  11. 使用CAS实现无锁列队-链表
  12. Python IDLE配置清屏快捷键(Ctrl+L)
  13. Flex布局—语法篇
  14. JAVA内存分配与回收策略
  15. HashMap底层结构、原理、扩容机制
  16. Visual Studio 2010 集成 SP1 补丁 制作 Visual Studio 2010 Service Pack 1 完整版安装光盘的方法
  17. webpack根据开发与生产环境配置不同变量--webpack.DefinePlugin
  18. B - Hamburgers
  19. js中forEach,for in,for of的区别
  20. 解决:SqlDateTime 溢出。必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之间提示问题

热门文章

  1. python使用zlib库压缩图片,使用ffmpeg压缩视频
  2. php 实现签名验签
  3. Ros中创建msg和srv遇到的问题
  4. SU模型叠加实景三维模型 用它就可以实现了
  5. 下载eclipse及其插件
  6. 卡特兰数 洛谷P1641 [SCOI2010]生成字符串
  7. 内网安装python第三方包
  8. jQuery其他事件
  9. 认识Redis集群——Redis Cluster
  10. 贼厉害,手撸的 SpringBoot 缓存系统,性能杠杠的!