【问题标题】:Spring Boot @Async method executing synchronouslySpring Boot @Async 方法同步执行
【发布时间】:2015-12-10 06:16:51
【问题描述】:

这与此处的另一个问题非常相似:Spring Boot @Async method in controller is executing synchronously。然而,我的 @Service@Async 注释的方法仍在同步执行。我已经尝试了来自不同论坛的所有方法,但没有用。希望有人能帮我弄清楚原因。如下一个简单的 spring boot 项目是行不通的。

AsyncConfiguration.java

@Configuration
@EnableAsync
public class AsyncConfiguration(){}

SomeService.java

@Service
public class SomeService() {
  @Async
  public void doSomething() {
    try {
      Thread.sleep(5000L);
    } catch (Exception ignore){}
  }
}

SomeController.java

@Controller
public class SomeController() {

  @Inject SomeService someService;

  @RequestMapping(value="/", method=RequestMethod.POST)
  public String doStuff() {
    someService.doSomething();
    return "mytemplate";
  }
}

【问题讨论】:

  • 你的AsyncConfiguration 上有一个@Configuration 对吗?
  • @StéphaneNic​​oll 是的,我愿意。我将编辑问题
  • 你的配置看起来很合法,所以问题的根源可能在其他地方。您能否在 github/bitbucket 上分享您的项目或创建 SSCCE (sscce.org)?
  • 你能把日志(带有线程名称的日志)放入 SomeService.dosomething() 并发布日志输出吗?
  • 如果有帮助,我正在使用@Service 类中的方法使用JavaMailSender 发送电子邮件

标签: java spring spring-boot


【解决方案1】:

这是一个使用@Async 的简单示例。按照以下步骤让 @Async 在您的 Spring Boot 应用程序中工作:

第1步:添加@EnableAsync注解并将TaskExecutor Bean添加到Application Class。

例子:

@SpringBootApplication
@EnableAsync
public class AsynchronousSpringBootApplication {

    private static final Logger logger = LoggerFactory.getLogger(AsynchronousSpringBootApplication.class);

    @Bean(name="processExecutor")
    public TaskExecutor workExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setThreadNamePrefix("Async-");
        threadPoolTaskExecutor.setCorePoolSize(3);
        threadPoolTaskExecutor.setMaxPoolSize(3);
        threadPoolTaskExecutor.setQueueCapacity(600);
        threadPoolTaskExecutor.afterPropertiesSet();
        logger.info("ThreadPoolTaskExecutor set");
        return threadPoolTaskExecutor;
    }

    public static void main(String[] args) throws Exception {
  SpringApplication.run(AsynchronousSpringBootApplication.class,args);
 }
}

第 2 步:添加执行异步进程的方法

@Service
public class ProcessServiceImpl implements ProcessService {

    private static final Logger logger = LoggerFactory.getLogger(ProcessServiceImpl.class);

    @Async("processExecutor")
    @Override
    public void process() {
        logger.info("Received request to process in ProcessServiceImpl.process()");
        try {
            Thread.sleep(15 * 1000);
            logger.info("Processing complete");
        }
        catch (InterruptedException ie) {
            logger.error("Error in ProcessServiceImpl.process(): {}", ie.getMessage());
        }
    }
}

第三步:在Controller中添加API来执行异步处理

@Autowired
private ProcessService processService;

@RequestMapping(value = "ping/async", method = RequestMethod.GET)
    public ResponseEntity<Map<String, String>> async() {
        processService.process();
        Map<String, String> response = new HashMap<>();
        response.put("message", "Request is under process");
        return new ResponseEntity<>(response, HttpStatus.OK);
    }

我还通过这些步骤在 GitHub 上写了一个博客和一个工作应用程序。请检查: http://softwaredevelopercentral.blogspot.com/2017/07/asynchronous-processing-async-in-spring.html

【讨论】:

  • 这是一个很好的例子,但是你知道为什么@vdkkj 的代码不起作用吗?
  • 如果您在我的回答中看到第 1 步,则会将一个名为 processExecutor 的 TaskExecutor Bean 添加到应用程序类中。这非常重要,在我的回答的第 2 步中使用。我在@vdkkj 的代码中没有看到。
  • @AjTechDeveloper:这可能不是问题,从官方入门blog:“如果你不定义Executor bean,Spring 会创建一个SimpleAsyncTaskExecutor 并使用它。
  • 嘿,你现在可以为帖子添加一个新的网址吗(2021 年网址坏了),提前谢谢
  • 嗨@qleoz12,博文网址与上面相同,并且正在运行:softwaredevelopercentral.blogspot.com/2017/07/…
【解决方案2】:

对不起我的英语。 同样的问题也发生在我身上。 解决方案是添加

@Autowired
private SomeService someService;

在Controller类中,这样可以让类包含与“SomeService”关联的Beam配置,从而可以完美的执行异步方法。

这是一个具有功能性异步方法的项目: https://github.com/JColmenares/async-method-api-rest.git

【讨论】:

    猜你喜欢
    • 2017-09-13
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多