通过14个入门实战案例教大家快速学习Python编程语言(python从入门到实践和Python编程快速上手)
442
2022-07-30
目录前言一、什么是异步任务二、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() {
RONixdo 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 是我们常用的功能,但是却不知道它真正的原理。日后遇到问题,要多从它的原理考虑。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~