热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

解决SpringBoot中使用@Async注解失效的问题

这篇文章主要介绍了解决SpringBoot中使用@Async注解失效的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

错误示例,同一个类中使用异步方法:

package com.xqnode.learning.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/test")
public class TestController {

 @GetMapping("/async")
 public Map test() throws InterruptedException, JsonProcessingException {
  System.out.println("接收到请求。。。");
  task();
  Map map = new HashMap<>();
  System.out.println("请求结束。。。");
  map.put("msg", "操作成功");
  map.put("code", "0");
  return map;
 }

 @Async
 void task() throws InterruptedException {
  TimeUnit.SECONDS.sleep(5);
  System.out.println("线程任务执行结束。。。");
 }
}

来分析下错误的原因:

当我使用postman调用该接口的时候发现,我预想中的立即返回并没有发生。后来查询资料发现,在controller调用本类中的异步方法,不会生效

正确示例:

package com.xqnode.learning.controller;

import com.xqnode.learning.service.AsyncService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/test")
public class TestController {

 private static final Logger LOG = LoggerFactory.getLogger(TestController.class);

 @Autowired
 private AsyncService asyncService;

 @GetMapping("/async")
 public Map test() throws InterruptedException {
  LOG.info("接收到请求。。。");
  asyncService.task();
  Map map = new HashMap<>();
  LOG.info("请求结束。。。");
  map.put("msg", "操作成功");
  map.put("code", "0");
  return map;
 }
}

将异步调用放到service中:

package com.xqnode.learning.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class AsyncService {

 private static final Logger LOG = LoggerFactory.getLogger(AsyncService.class);


 @Async("asyncExecutor")
 public void task() throws InterruptedException {

  TimeUnit.SECONDS.sleep(5);
  LOG.info("线程任务执行结束。。。");
 }
}

这时候再重启项目请求该接口,就会发现接口可以立即返回值。而task任务是异步执行的,5秒之后才会打印结果:

补充知识:springboot + @Async 实现异步方法之踩坑填坑

在使用@Async注解实现异步方法的时候,我们项目中实现了AsyncConfigurer接口来自定义线程池和异常处理。其中自定义线程池的代码如上图,异常处理项目中是自定义异常类实现AsyncUncaughtExceptionHandler 接口,这里未贴出代码。那么到底踩了什么坑呢?

第一:

加了@Async注解的方法调不起来。由于我不是项目及代码的原创,花了很多时间才分析出问题。经过仔细分析,由于业务场景需要,我们在项目启动的时候就创建了3个线程(也就是创建了3个任务)这正好占满了核心线程数(3个),当调到@Async的方法时,相当于有新的任务进来,结合线程池的原理可知,新的任务都会放到阻塞队列里面去,直到阻塞队列满了才可能会创建新的线程来执行任务或者执行饱和策略(这与Runtime.getRuntime().availableProcessors()能获取到的线程数有关),所以造成了异步方法调不起来的假象。

解决方法:根据实际情况将线程池的核心线程数和最大线程数调整到合适的值。

第二:

在解决了上一个问题后,又发现了新的问题,后面某段代码看不到执行的日志,也不知道错在哪里,没有错误日志。由于之前项目的日志并不详细,在逐步完善各处日志后,终于发现问题,报出了某个实体类没有默认构造函数的错误。在@Async异步方法中有一个把json转成实体bean的操作,由于这个bean创建了有参构造函数,却没有默认的无参构造函数,所以抛异常了,正好被getAsyncUncaughtExceptionHandler()捕捉到,由于当时此方法没有日志,也是花了点时间的。

解决方法:完善日志,给实体类加上无参构造函数。

通过这两个问题,自己也总结了一下,在使用线程池相关的知识时,一定要先了解原理,不然可能给自己挖坑,还有就是平常写代码时要养成写注释和打日志的习惯,否则出问题时可能要多花很久的时间找问题。

以上这篇解决SpringBoot中使用@Async注解失效的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


推荐阅读
  • 本文介绍了如何使用Postman构建和发送HTTP请求,包括四个主要部分:方法(Method)、URL、头部(Headers)和主体(Body)。特别强调了Body部分的重要性,并详细说明了不同类型的请求体。 ... [详细]
  • 本文探讨了 RESTful API 和传统接口之间的关键差异,解释了为什么 RESTful API 在设计和实现上具有独特的优势。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 本文档详细规划了从基础到高级的软件测试学习路径,包括但不限于测试基础、Linux和数据库、功能测试、Python编程、接口测试、性能测试、金融项目实战、UI自动化测试等内容,旨在为初学者和进阶者提供全面的学习指导。 ... [详细]
  • 在使用Postman进行接口测试时,如果携带大量参数,可能会遇到‘请求头过大’的问题。本文将详细介绍如何调整Tomcat的请求头大小限制,并提供有效的路径映射解决方案,以避免因路径配置不当导致的404错误。 ... [详细]
  • 本文探讨了如何在Sitecore 9环境中通过Postman使用API密钥发送请求,包括解决常见错误的方法。 ... [详细]
  • 利用爬虫技术抓取数据,结合Fiddler与Postman在Chrome中的应用优化提交流程
    本文探讨了如何利用爬虫技术抓取目标网站的数据,并结合Fiddler和Postman工具在Chrome浏览器中的应用,优化数据提交流程。通过详细的抓包分析和模拟提交,有效提升了数据抓取的效率和准确性。此外,文章还介绍了如何使用这些工具进行调试和优化,为开发者提供了实用的操作指南。 ... [详细]
  • 本文介绍如何在PostgreSQL数据库中正确插入和处理JSON数据类型,确保数据完整性和避免常见错误。 ... [详细]
  • 作为一名 Ember.js 新手,了解如何在路由和模型中正确加载 JSON 数据是至关重要的。本文将探讨两者之间的差异,并提供实用的建议。 ... [详细]
  • 本文详细介绍了在企业级项目中如何优化 Webpack 配置,特别是在 React 移动端项目中的最佳实践。涵盖资源压缩、代码分割、构建范围缩小、缓存机制以及性能优化等多个方面。 ... [详细]
  • 选择适合生产环境的Docker存储驱动
    本文旨在探讨如何在生产环境中选择合适的Docker存储驱动,并详细介绍不同Linux发行版下的配置方法。通过参考官方文档和兼容性矩阵,提供实用的操作指南。 ... [详细]
  • 本文详细介绍了Ionic框架的使用方法及其与Angular的集成。Ionic框架是一个强大的前端开发工具,适用于构建跨平台的移动应用程序。文章将探讨如何引入必要的CSS和JavaScript文件,并解释bundle.js中包含的核心功能,如路由等。 ... [详细]
  • 自 Node.js 6.3 版本起,调试功能已内置在核心模块中,无需额外安装 node-inspector 等工具。通过简单的命令即可启动调试模式,并利用 Chrome 浏览器进行高效的代码调试。 ... [详细]
  • 提升接口测试效率的关键:用例与工具的综合应用
    本文将探讨如何通过有效的接口测试用例设计和工具选择,显著提高接口测试的效率和质量。 ... [详细]
  • HTTP中的Chunked编码与Content-Length的区别及应用场景
    本文探讨了在HTTP协议中,当使用Transfer-Encoding为chunked时为何无需设置Content-Length,以及这种编码方式的具体实现和优势。 ... [详细]
author-avatar
回__复卷轴
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有