一次java异步任务的实战记录

目录
  • 前言
  • 一、什么是异步任务
  • 二、SpringBoot + Async
  • 三、踩坑日记
  • 四、解决
  • 五、总结

前言

最近在开发中遇到一个埋点的需求,考虑到不能影响原有业务逻辑,于是准备写一个异步任务去异步执行,但在 debug 的过程中却发现了一个奇怪的问题。

一、什么是异步任务

无论是生活中还是程序里,大体可以分为两种 : 同步和异步。

同步:比如你去吃海底捞,你要先点锅底,再点菜,然后服务员上锅底,再上菜,最后你才能吃上菜,这一过程得按顺序来。

异步任务:还是去吃海底捞,吃的人很多,你前面有很多人,你可能要排队,等到排到你才能再进入餐厅。但是如果中途你想去个厕所,怎么办,回来还得重新排队。于是就有了叫号,你先排队取号,然后你可以去按个摩,看个电影,做个 spa ,买杯奶茶 .... 。终于到你了,这时候会 通知 你排到了,然后你就能进去了。这个过程便是异步的。

二、SpringBoot + Async

一开始想着开一个线程池,把任务丢线程池里去完成。

后来想起来 SpringBoot 有一个比较方便的 异步 框架 Async

代码也很简单,只需要在需要异步执行的方法上加个 @Async ,SpringBoot 启动类上添加  @EnableAsync 即可

    @Async
    public void task() {
        // do something
    }

三、踩坑日记

代码虽然少,但是坑可不会随着代码量的减少而减少。

为了方便起见,我本地搭了个 demo,直接上代码

@RestController
public class AsyncController {
    @Autowired
    private AsyncService asyncService;

    @GetMapping("/v1/say")
    public String sayV1() {
        asyncService.sayV1();
        return "success1";
    }

    @GetMapping("/v2/say")
    public String sayV2() {
        asyncService.sayV2();
        return "success2";
    }
}
@Service
public class AsyncService {
    public void sayV1() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello world");
    }

    @Async
    public void sayV2() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello world");
    }
}

很简单的 demo,提供两个接口,/v1/say 和 /v2/say,一个同步执行,一个异步执行,通过 sleep 3 秒来模拟耗时的任务

正常启动,没有任何问题,同步执行的等 3 秒,主线程才会返回,异步执行的立刻返回,等3 秒才会输出 helloworld

但是,当我加上断点后,问题产生了。

我先是在 打印 hello world 那行加上个断点,效果和原来的一样,只是打印前被阻塞了,但并不影响主线程的返回。

​编辑

但当我把断点加在方法进来的位置,发现 主线程居然被阻塞了!

​编辑

四、解决

各种问题排查,@Async 没有生效,异步任务等待主线程返回,都没有找到有效的解决方法。

后来经过一个同事提醒,会不会是 debug 功能阻塞的线程呢?

抱着试一试的态度,我找到了 debug 这边的配置

​编辑

断点可以选择阻塞 jvm 或者是 阻塞当前线程,默认是阻塞 jvm。

将 suspend 选择 Thread,便不会再阻塞主线程了

五、总结

我们都是站在巨人的肩膀上编程,很多事情都是只知其果,不知其因,debug 是我们常用的功能,但是却不知道它真正的原理。日后遇到问题,要多从它的原理考虑。

到此这篇关于一次java异步任务的文章就介绍到这了,更多相关java异步任务内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java从源码看异步任务计算FutureTask

    目录 了解一下什么是FutureTask? FutureTask 是如何实现的呢? FutureTask 运行流程 FutureTask 的使用 前言: 大家是否熟悉FutureTask呢?或者说你有没有异步计算的需求呢?FutureTask就能够很好的帮助你实现异步计算,并且可以实现同步获取异步任务的计算结果.下面我们就一起从源码分析一下FutureTask. 了解一下什么是FutureTask? FutureTask 是一个可取消的异步计算. FutureTask提供了对Future的基本实

  • 一次java异步任务的实战记录

    目录 前言 一.什么是异步任务 二.SpringBoot + Async 三.踩坑日记 四.解决 五.总结 前言 最近在开发中遇到一个埋点的需求,考虑到不能影响原有业务逻辑,于是准备写一个异步任务去异步执行,但在 debug 的过程中却发现了一个奇怪的问题. 一.什么是异步任务 无论是生活中还是程序里,大体可以分为两种 : 同步和异步. 同步:比如你去吃海底捞,你要先点锅底,再点菜,然后服务员上锅底,再上菜,最后你才能吃上菜,这一过程得按顺序来. 异步任务:还是去吃海底捞,吃的人很多,你前面有很

  • java版飞机大战实战项目详细步骤

    本文为大家分享了java版飞机大战实战项目,供大家参考,具体内容如下 分析 飞机大战 首先对这个游戏分析,在屏幕上的物体都是飞行物,我们可以把建一个类,让其他飞行物继承这个类.游戏中应有英雄机(也就是自己控制的飞机).敌人.而敌人应该分为打死给分的飞机(就是普通飞机),另一种就是打死有奖励的敌人.他们都应该是飞行物的子类,我们也可以为普通飞机和给奖励的敌人设一个接口让他们去实现接口,这样有利于以后的扩展,我在这里给的简化版的飞机大战,主要是为了让大家了解面向对象. 第一步建立飞行物类 impor

  • Java异步非阻塞编程的几种方式总结

    1 服务端执行,最简单的同步调用方式: 缺陷: 服务端响应之前,IO会阻塞在: java.net.SocketInputStream#socketRead0 的native方法上: 2 JDK NIO & Future java 1.5之后 优点:主线程可以不用等待IO响应,可以去做点其他的,比如说再发送一个IO请求,可以等到一起返回; 缺点:主线程在等待结果返回过程中依然需要等待,没有根本解决此问题; 3 使用Callback回调方式 优点:主线程完成发送请求后,再也不用关心这个逻辑,去执行其

  • Java 异步实现的几种方式小结

    Java 异步实现的几种方式 1. jdk1.8之前的Future jdk并发包里的Future代表了未来的某个结果,当我们向线程池中提交任务的时候会返回该对象,可以通过future获得执行的结果,但是jdk1.8之前的Future有点鸡肋,并不能实现真正的异步,需要阻塞的获取结果,或者不断的轮询. 通常我们希望当线程执行完一些耗时的任务后,能够自动的通知我们结果,很遗憾这在原生jdk1.8之前是不支持的,但是我们可以通过第三方的库实现真正的异步回调. /** * jdk1.8之前的Future

  • SpringBoot实战记录之数据访问

    目录 前言 SpringBoot整合MyBatis 环境搭建 注解方式整合mybatis 使用xml配置Mybatis 整合Redis 接口整合 测试 总结 前言 在开发中我们通常会对数据库的数据进行操作,SpringBoot对关系性和非关系型数据库的访问操作都提供了非常好的整合支持.SpringData是spring提供的一个用于简化数据库访问.支持云服务的开源框架.它是一个伞状项目,包含大量关系型和非关系型数据库数据访问解决方案,让我们快速简单的使用各种数据访问技术,springboot默认

  • Java中的JetCache 实战

    目录 1.JetCache 是什么? 2.使用方法 1.JetCache 是什么? JetCache是一个基于Java的缓存系统封装,提供统一的API和注解来简化缓存的使用. JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL.两级缓存.分布式自动刷新,还提供了Cache接口用于手工缓存操作. 当前有四个实现,RedisCache.TairCache(此部分未在github开源).CaffeineCache(in memory)和一个简易的LinkedHashMa

  • Go使用proto3的踩坑实战记录

    开发环境:windows10,golang1.18.2,goland2022.2 最近在写项目时,一些数据类的结构以protobuf文件给定.因此,需要将这些protobuf文件转换为golang代码. 首先,在下载解析protobuf的包的时候就碰到了第一个问题... go get -u github.com/golang/protobuf/protoc-gen-go 在我用上述命令后,终端提示该包已弃用 go: module github.com/golang/protobuf is dep

  • java异步编程的7种实现方式小结

    目录 同步编程 一.线程 Thread 二.Future 三.FutureTask 四.异步框架 CompletableFuture 五. SpringBoot 注解 @Async 六.Spring ApplicationEvent 事件 七.消息队列 最近有很多小伙伴给我留言,能不能总结下异步编程,今天就和大家简单聊聊这个话题. 早期的系统是同步的,容易理解,我们来看个例子 同步编程 当用户创建一笔电商交易订单时,要经历的业务逻辑流程还是很长的,每一步都要耗费一定的时间,那么整体的RT就会比较

  • 简述Java异步上传文件的三种方式

    本文为大家分享了三种Java异步上传文件方式,供大家参考,具体内容如下 用第三方控件,如Flash,ActiveX等浏览器插件上传. 使用隐藏的iframe模拟异步上传. 使用XMLHttpRequest2来实现异步上传. 第一种使用浏览器插件上传,需要一定的底层编码功底,在这里我就不讲了,以免误人子弟,提出这点大家可以自行百度. 第二种使用隐藏的iframe模拟异步上传.为什么在这里说的是模拟呢?因为我们其实是将返回结果放在了一个隐藏的iframe中,所以才没有使当前页面跳转,感觉就像是异步操

  • Java 异步回调机制实例分析

    Java 异步回调机制 一.什么是回调 回调,回调.要先有调用,才有调用者和被调用者之间的回调.所以在百度百科中是这样的: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用. 回调是一种特殊的调用,至于三种方式也有点不同. 1.同步回调,即阻塞,单向. 2.回调,即双向(类似自行车的两个齿轮). 3.异步调用,即通过异步消息进行通知. 二.CS中的异步回调(Java案例) 比如这里模拟个场景:客户端发送msg给服务端,服务端处理后(5秒),回调给客户端

随机推荐