一、引言

在前边的文章《[springboot:使用异步注解@Async的那些坑》中介绍了使用@Async注解获取任务执行结果的错误用法,今天来分享下另外一种常见的错误。

二、代码演示

下面是我的controller的代码,

package com.atssg.controller;

import com.atssg.service.MyAsyncService;
import lombok.extern.slf4j.Slf4j;
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; @Slf4j
@RequestMapping("/sync/")
@RestController
public class SyncController2 {
@Autowired
private MyAsyncService syncService; @GetMapping("/test2")
public String test2() {
return syncService.syncMethod("hello world");
}
}

在controller中调用了service层的syncMethod方法,下面看该方法的定义,

package com.atssg.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@Slf4j
@Service
public class MyAsyncService {
@Autowired
private SyncService syncService;
public String syncMethod(String str) {
String result = null;
try {
log.info("start,{}",System.currentTimeMillis());
//调用method4方法,该方法中会桥套调用另外一个异步方法
Future<String> futureResult = syncService.method4(str);
result = futureResult.get();
log.info("end:{}",System.currentTimeMillis());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return result;
}
}

method4方法是一个异步的方法,在该方法内部会调用另外一个异步的方法,下面看该method4方法的定义,

/**
* 调用另一个异步方法
*
* @param str
* @return
* @throws InterruptedException
*/
public Future<String> method4(String str) throws InterruptedException { //method4方法睡眠10s
Thread.sleep(1000 * 10);
//调用另外一个异步方法
method1(str);
return new AsyncResult<>(str);
}

下面看method1方法,

public Future<String> method1(String str) throws InterruptedException {
Thread.sleep(1000 * 10);
return new AsyncResult<>(str);
}

该方法也是睡眠10s。另外这两个方法均是异步方法,有小伙伴会疑惑,怎么没有标注异步注解@Async那,这是因为该注解可以用在方法上也可以用在类上,在前面的文章中说过,不知道小伙伴还记得吗,不清楚的可以再看下给注解的定义哦。下面是我的类,大体看下,

小伙伴们看到了吗,我是在类上标注了@Async的哦,这样对于该类中所有的方法都是起作用的,即所有方法都是异步的。

按照正常的逻辑来分析,method4和method1都是异步方法,且两个方法均睡眠10s,那么异步执行的结果应该是10s多点,但这里是在method4中调用了method1,即嵌套调用,那么结果会是什么样子那。看下执行结果,

看到这个执行结果小伙伴是不是很惊讶,执行时间大约是20s多点,不相信的小伙伴可以多执行几次,结果发现都是20s多点,这是为什么,不应该是10s多点,难道异步执行失效了吗

三、总结

在异步方法中调用另外一个异步方法会导致异步执行失败,就是上面的执行结果,所以不要在异步方法中再调用异步方法,达到异步执行的目的。有小伙伴会问这是为什么那,事先透露下这个要从异步的原理说起,异步的原理是通过代理实现的,更多内容欢迎关注下集更精彩。

推荐阅读

springboot:使用异步注解@Async获取执行结果的坑

springboot:异步调用@Async

springboot:嵌套使用异步注解@Async还会异步执行吗的更多相关文章

  1. springboot:使用异步注解@Async的前世今生

    在前边的文章中,和小伙伴一起认识了异步执行的好处,以及如何进行异步开发,对,就是使用@Async注解,在使用异步注解@Async的过程中也存在一些坑,不过通过正确的打开方式也可以很好的避免,今天想和大 ...

  2. springboot:使用异步注解@Async的那些坑

    springboot:使用异步注解@Async的那些坑 一.引言 在java后端开发中经常会碰到处理多个任务的情况,比如一个方法中要调用多个请求,然后把多个请求的结果合并后统一返回,一般情况下调用其他 ...

  3. Spring中异步注解@Async的使用、原理及使用时可能导致的问题

    前言 其实最近都在研究事务相关的内容,之所以写这么一篇文章是因为前面写了一篇关于循环依赖的文章: <面试必杀技,讲一讲Spring中的循环依赖> 然后,很多同学碰到了下面这个问题,添加了S ...

  4. 关于Dubbo和Spring异步注解@Async的冲突

    项目中难免会有异步处理的需求,像异步记录日志啦,异步发送邮件啦,而Dubbo又是现在主流的分布式框架,所有异步+Dubbo的组合是再所难免的 但博主是实践中发现Dubbo的服务并不能很好的跟Sprin ...

  5. Java中异步注解@Async的陷阱

    或许,你在Java后端添加异步过程时会这样处理,然后摇摇大摆.灰溜溜地闪,而实际的运行结果却并不是我们期望的那样.那么,现在就将试验结果记录如下,以便少走弯路. (一)在Controller层的公开接 ...

  6. @Async异步注解与SpringBoot结合使用

    当你在service层需要启动异步线程去执行某些分支任务,又不希望显式使用Thread等线程相关类,只想专注于实现业务逻辑代码开发,可以使用@Async异步注解. 1. 使用@Async 异步注解 C ...

  7. SpringBoot系列——@Async优雅的异步调用

    前言 众所周知,java的代码是同步顺序执行,当我们需要执行异步操作时我们需要创建一个新线程去执行,以往我们是这样操作的: /** * 任务类 */ class Task implements Run ...

  8. SpringBoot学习笔记(七):SpringBoot使用AOP统一处理请求日志、SpringBoot定时任务@Scheduled、SpringBoot异步调用Async、自定义参数

    SpringBoot使用AOP统一处理请求日志 这里就提到了我们Spring当中的AOP,也就是面向切面编程,今天我们使用AOP去对我们的所有请求进行一个统一处理.首先在pom.xml中引入我们需要的 ...

  9. springboot:异步调用@Async

    在后端开发中经常遇到一些耗时或者第三方系统调用的情况,我们知道Java程序一般的执行流程是顺序执行(不考虑多线程并发的情况),但是顺序执行的效率肯定是无法达到我们的预期的,这时就期望可以并行执行,常规 ...

随机推荐

  1. MySQL中的redo log和undo log

    MySQL中的redo log和undo log MySQL日志系统中最重要的日志为重做日志redo log和归档日志bin log,后者为MySQL Server层的日志,前者为InnoDB存储引擎 ...

  2. DataGridView 显示行号与背景颜色

    实现的方式有好几种.之前使用的是下面这种在RowPostPaint事件中实现,效率不高.每次改变控件尺寸时都会执行 private void MsgGridView_RowPostPaint(obje ...

  3. JAVA,IDEA下的包机制

    IDEA下的包机制 在实际开发中,大型系统往往需要多人合作完成,每个程序员都要命名多个类与接口等类型,难免会定义重复的类与接口.为了避免名字冲突,java提供了包机制只要包名不同,即使类名相同,也能相 ...

  4. SickOs1.2靶机

    仅供个人娱乐 靶机信息 靶机下载地址:https://www.vulnhub.com/entry/sickos-12,144/一.主机发现  arp-scan -l 二.端口扫描 1. masscan ...

  5. Python中input()函数用法

    input()函数获取用户输入数据,实现用户交互 语法格式: 变量 = input("提示信息") input()返回的是字符串,无论输入的是数字还是字符串,默认的输入结束键是回车 ...

  6. 五、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之MVVM中的EventAggregator

    这一篇我们主要再看完示例12.13后,写了个例子,用于再Modules下执行ApplicationCommands,使用IActiveAware执行当前View的Commands,或者Applicat ...

  7. 数据结构与算法-排序(六)堆排序(Heap Sort)

    摘要 堆排序需要用到一种数据结构,大顶堆.大顶堆是一种二叉树结构,本质是父节点的数大于它的左右子节点的数,左右子节点的大小顺序不限制,也就是根节点是最大的值. 这里就是不断的将大顶堆的根节点的元素和尾 ...

  8. Package Repository for Ubuntu Offline Installation

    For example, we need install "unzip" command on a Ubuntu machine without Internet. On a on ...

  9. Linux进程理解与实践(一)基本概念和编程概述(fork,vfork,cow)

    进程 and 程序 什么是程序? 程序是完成特定任务的一系列指令集合. 什么是进程? [1]从用户的角度来看:进程是程序的一次执行过程 [2]从操作系统的核心来看:进程是操作系统分配的内存.CPU时间 ...

  10. git submodule 操作

    git submodule foreach git status 举一反三,对所有子库的操作,都可以使用 git submodule foreach 做前缀 foreach,可以记忆为for each ...