欢迎关注方志朋的博客,回复”666“获面试宝典


在很久很久之前,我有一段痛苦的记忆。那种被故障所驱使的感觉,在我脑海里久久无法驱散。

原因无它,有小伙伴开启了线程池的暴力使用模式。没错,就是下面这篇文章。

夺命故障 ! 炸出了投资人!

我有必要简单的复述一下。其主要原因,就是开发人员,在每一次方法调用里,都创建了一个单独的线程池去处理。这样的话,如果请求量一增加,整个操作系统的压力就会耗尽,最终所有的业务都无法响应。

我一直认为这是一个非常偶发的低级错误,发生频率非常的低。但随着这样的故障越来越多,xjjdog认识到这是一个普遍的现象。

以异步性能优化为目的,反而带来的整体业务不可用的结果,是非常打脸的一种优化。

1.Spring的异步代码

Spring作为Java届的杠把子框架,其过度封装的API深得开发人员的喜爱。根据语义化编程的逻辑,只要某些关键字在语言层面上过得去,我们就可以把它给加上去。比如@Async注解。

我永远想不通是什么给了开发人员勇气,去加上这个@Async注解,因为这种涉及到多线程的东西,即使是自己去创建线程,也是心怀敬畏,唯恐扰了操作系统的安宁。@Async这样的黑盒,真的可以那么顺畅的使用么?

我们不妨debug一下代码,让子弹飞一会儿。

首先,生成一个小小的项目,然后在主类上加上必须的注解。嗯,别忘了这一环,否则你后面加的注解将没什么用处。

@SpringBootApplication
@EnableAsync
public class DemoApplication {

创造一个带@Async注解的方法。

@Component
public class AsyncService {@Asyncpublic void async(){try {Thread.sleep(1000);System.out.println(Thread.currentThread());}catch (Exception ex){ex.printStackTrace();}}
}

然后,做一个对应的test接口,访问时会调用这个async方法。

@ResponseBody
@GetMapping("test")
public void test(){service.async();
}

访问时,直接打个断点,即可获取执行异步线程的线程池。

可以看到,异步任务使用了一个线程池,它的corePoolSize=8, 阻塞队列采用了无界队列LinkedBlockingQueue。一旦采用了这样的组合,最大线程数就会形同虚设,因为超出8个线程的任务,将全部会被放到无界队列里。使得下面的代码变成了摆设。

throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, var4);

如果你的访问量非常大,这些任务将全部堆积在LinkedBlockingQueue里。情况好一点的,这些任务的执行会变得延迟很大;情况坏一点的,任务太多将直接造成内存溢出OOM!

你可能会说,我可以自己指定另外一个ThreadPoolExceute,然后使用@Async注解来声明啊。说这话的同学,一定是能力比较强,或者Review的代码比较少,没有经过猪队友的洗礼。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

2.是SpringBoot救了你

SpringBoot是个好东西。

在TaskExecutionAutoConfiguration中,通过生成ThreadPoolTaskExecutor的Bean,来提供默认的Executor。

@ConditionalOnMissingBean({Executor.class})
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {return builder.build();
}

也就是我们上面所说的那个。如果没有SpringBoot的助力,Spring将默认使用SimpleAsyncTaskExecutor。

参见org.springframework.aop.interceptor.AsyncExecutionInterceptor。

@Override
@Nullable
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {Executor defaultExecutor = super.getDefaultExecutor(beanFactory);return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}

这就是Spring大仙所干的事。

SimpleAsyncTaskExecutor类设计的非常操蛋,因为它每执行一次,都会创建一个单独的线程,根本没有共用线程池。比如你的TPS是1000,异步执行了任务,那么你每秒将会生成1000个线程!

这明显是想要累死操作系统的节奏。

protected void doExecute(Runnable task) {Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));thread.start();
}

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

项目地址:https://github.com/YunaiV/onemall

3.End

明眼人一看,这种使用new线程的处理方式将会是非常可怕的。但就拿Spring本身来说,引用SimpleAsyncTaskExecutor这个类的地方还不少,包括比较流行的AsyncRestTemplate。

这暴露了很多风险,尤其是竟然在这些列表中看到了redis的身影。这个类的设计,使得任务的执行变的非常的不可控。

看这个API,我感觉Spring是进入了设计的魔怔状态。

这个东西的隐藏bug可能还会更深!比如org.springframework.context.event.EventListener注解,用于实现DDD那套所谓的事件驱动模式,有不少框架直接set了SimpleAsyncTaskExecutor,那么就等死吧。

赶紧把SimpleAsyncTaskExecutor加入你的API黑名单,或者埋坑清单吧!

创建线程有那么难么?需要使用Spring创建的线程?有时候我实在是想不通,暴露出这样的接口目的是为了什么。

就连原生的线程池我们还没搞明白呢,你还给包了一层,这是方便我们甩锅啊!

热门内容:

  • 最新 955 不加班的公司名单(2022版)

  • 我妈今年 70 岁,受不了Windows蓝屏,用了 21 年的 Linux!YYDS!

  • 京东一面:Spring 为何需要三级缓存解决循环依赖,而不是二级缓存?我懵了。。

  • 牛啊,又一份牛逼笔记面世了

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

新来了个技术总监:谁再用 @Async 创建线程以后就不用来了!!相关推荐

  1. 为什么CTO、技术总监、架构师都不写代码,还这么牛逼?

    常常会被问到这样的问题:CTO.技术总监.架构师很少写具体代码,为什么还很牛逼的样子,拿这么高工资? 其实,这个问题本身就错了.就好比问:导演.制片人为什么不懂演戏,还能指导演员,好像比演员厉害似的? ...

  2. 为什么 CTO、技术总监、架构师都不写代码,还这么牛?

    作者| Mr.K   整理| Emma 来源| 技术领导力(ID:jishulingdaoli) 常常会被问到这样的问题:CTO.技术总监.架构师很少写具体代码,为什么还很牛逼的样子,拿这么高工资? ...

  3. 研发管理(2)---技术总监的三板斧

    说说技术总监的三板斧 2018一转眼就过去了1/6还要多,这个时间想必很多人都在思考职业规划,甚至是要不要另谋高就,作为一个老技术人,今天不聊技术,就聊点技术人员职业发展的事情:对技术管理岗位的认知, ...

  4. #为何程序员百万年薪,CTO技术总监架构师不写代码还这么牛逼 ?

    [此文章转自乐字节] 真的是一点不服气我的领导,每天就在座位上看看头条,到时间开开会,每天写代码的时间可能不到两小时,到底是为什么他的收入有年薪百万?我们都是985研究生毕业,是什么铸就了他的价值? ...

  5. 技术总监/技术leader 职责与工作记录 第二天(包含技术部门规范示例)

    第二天 入职的一个重点:交接项目. 目前还没有招聘到开发人员,所有重点放在熟悉现有公司网络资产上,内容包括: 服务器使用情况,自有机房,还是云服务器 数据库使用情况,数据库版本,包括关系型和非关系型 ...

  6. 对话七牛云技术总监陈辉:音视频行业中的新系统新规划和新增长

    编者按: 从去年七牛云音视频团队发布音画质量分析系统到现在已有半年多的时间,得到了很多业内玩家和客户的认可.在即将召开的 LiveVideoStackCon 2022 音视频技术大会上海站,七牛云将以 ...

  7. 一个网瘾少年到腾讯码农,再到360技术总监,最后成长为CTO的逆袭之路!太艰难了.....

    点赞再看,养成习惯,微信搜一搜[findyi]关注这个喜欢写情怀的程序员. 回复[1]获得程序员职场晋升PPT一份 我曾经是一个游戏网瘾少年.6岁就开始玩街机,之后开始玩小霸王游戏机,初中三年长期混迹 ...

  8. 去了家新公司,技术总监不让用 IntelliJ IDEA!!想离职了。。

    最近有个小伙伴微信和我说,新去的一家公司,技术团队全部规定要用的 Eclipse 开发,技术总监不让用 IntelliJ IDEA,付费也不行,说想离职了,问我该怎么办. 首先听到这件事情的时候,我表 ...

  9. 去了家新公司,技术总监不让用 IntelliJ IDEA想离职了

    最近有个小伙伴微信和我说,新去的一家公司,技术团队全部规定要用的 Eclipse 开发,技术总监不让用 IntelliJ IDEA,付费也不行,说想离职了,问我该怎么办. 首先听到这件事情的时候,我表 ...

最新文章

  1. 信息服务器怎么填写,如何设定服务器信息
  2. databtables 设置(显示)行号
  3. ForkJoinPool分支合并框架计算加法
  4. 计算机组成原理 第五章 中央处理器
  5. UVA11878 Homework Checker【文本】
  6. 毕业前五年,我们应该把钱看轻
  7. 《OpenCV算法精解——基于Python与C++》第六章阈值分割
  8. selenium中整个页面的截图及局部截图(方法分析)
  9. 网易邮箱添加附件功能原理浅析
  10. Sicily 1484. 守望者的逃离
  11. LTS = Long Term Support:长期支持版本
  12. RTC编程挑战赛 开源项目推荐
  13. RPG游戏经典的系统架构
  14. 学完C语言可以学什么--C/C++图形库Easyx(万字教程,一文入门)
  15. 大学计算机基础实验指导第一章答案,(教材)大学计算机基础实验指导与习题解答...
  16. LibreOJ #6177. 「美团 CodeM 初赛 Round B」送外卖2【状压DP】
  17. Windows不能在本地计算机启动TOMCAT
  18. PHP获取某一年的每个星期六星期天
  19. 如何用计算机cmd算数,计算命令:怎么在CMD的计算器命令是什么?
  20. 【网络基础】qps | tps | pv | uv

热门文章

  1. 打印不同对象的字节表示 ( 对int*强制转换成unsigned char*的理解 )
  2. Codeforces 894.D Ralph And His Tour in Binary Country
  3. Entity Framework的启动速度优化
  4. Swift从零开始学习_08(代理协议传值)
  5. 【摘录】GestureDector使用
  6. visual studio 2005 新建C++空项目无法调试的解决方案
  7. 数据结构与算法:12 数组与稀疏矩阵
  8. 刻意练习:LeetCode实战 -- Task08.删除排序链表中的重复元素
  9. Matlab数据的可视化 -- 茎干图
  10. 什么是SESSION?(三)