浅谈JUC的理解
- 一、前言感悟
- 二、并发知识
- 三、一年前回答
- 四、补充体系回答
- 五、补充层次回答
- 六、碎碎念
本文除了说技术,更多的是在一个两年多开发经验的程序员视角下,记录下自己探索到的世界。
如有不妥之处,还请指正。共勉。
一、前言感悟
当我们在谈一个技术的时候,不要过多的陷入技术本身,我们需要明白技术是服务业务的。今天的我们需要以一个更为广阔的视角去看待技术,多去看看、思考那些技术细节以外的东西。
JUC同理。这部分涉及知识点相对较多,属于是八股文的重灾区。仔细想来,这已经是自己第三次学习JUC知识了,第一次学习如何使用,第二次学习相关八股知识点,那这一次自己要学什么?换句话说就是,这次学习自己能收获什么?常年行走在B端产品里,老实说,使用并发工具的频率并不高。在八股同质化严重的今天,一部分人选择了卷深度,无奈自己记忆力确实不太行,且对当下的自己来说ROI太低,那自己的差异点能在哪里?昨天和小伙伴们简单讨论了下并发相关的知识点,突然有感而发,实习的时候就是这些东西,今天还是这些,八股文到头了?
然后瞬间灵感了一个idea,我这次学习可以梳理一下并发知识体系,让这些并发的知识点长在一棵树上。这样下次别人再问我谈谈JUC的理解,我就不会一张口就提被说烂了的synchronized、AQS这些干涩的知识点,而是更有体系,更有血有肉的东西(目的)。
二、并发知识
回到JUC本身,引入多线程是为了解决单线程下资源和性能的平衡问题,但是在使用多线程的时候又遇到了新的问题——线程安全问题。遇到了问题,我们就要解决问题。我将JUC的回答归纳为了两个问题:
- 如何又好又快的解决线程安全问题?
- 多线程如何为我们的生产力提效?
顺着这个思路,我将JUC部分涉及到的大部分东西都融入到了这一张xmind中
知识有体系、有深度了,那如何回答呢?
三、一年前回答
侧重回答原理层面的,融合了很多热门的八股文考点
要是面试官再问我volatile,我就这么答
要是面试官再问我synchronized,我就这么答
四、补充体系回答
主要是补充这个知识点在JUC并发体系中的位置
举个例子,今天之前你让我说对ThreadLocal的理解,我可能就只会说ThreadLocalMap、强软弱虚引用、内存泄漏、甚至引申JVM定位内存泄漏问题。在梳理了并发体系后,我就可以补充:
-
它的作用是什么?解决线程间数据隔离的一个工具;
-
它在JUC中定位是什么?多线程的基础工具,辅助作用;
-
它和其他什么多线程知识点有什么联动?Thread。
可我今天想说,我觉得还能再优化。
五、补充层次回答
有感于职场这一年多技术方案评审时的耳濡目染,我甚至觉得可以再拔高一下这个问题的回答角度。从我们介绍一个东西的思路出发,将它说的更有层次,最终来体现我们看问题更全面、更专业。
八股文大家都会背,面试比记忆力?比谁会卷操作系统源码?起码我不希望往这个方向走,我当下能想到的解法就是——从更全面的分析问题的角度去分析我们的技术点,而在这个过程中,除了能够反映我的技术知识,还能反映出我们思考问题的方式方法(我始终觉得思考问题的方式方法对人成长的影响很大),顺便降低了原理部分对于整体技术点理解的比重(避重就轻)。
也有难度(换了个方向卷),甚至还有些冗余和深沉,但这已经是我当下能想到的在千篇一律的八股文面试中具有独特之处的最优解了(如果几年后回头看,打脸了自己,那么我很开心,因为自己成长了)。
那么我的谈谈就可以贯穿这些问题去讲:
- 它是什么?解决线程间数据隔离的一个工具;
- 它解决了什么问题?设置的参数可以在同一个线程的任意位置获取到;
- 它怎么解决的这个问题(同一个线程任意位置获取到)?是Thread的成员变量,不同线程自己维护自己的,只要在当前线程内就能通过方法调用获取到参数;
- 如何为我们的业务提供帮助?核心思路,在什么场景下,遇到了什么问题,怎么解决。业务中,形式参数传递用户太麻烦,使用它传递用户上下文,分布式tradeId等;框架中,使用@Autwired引入的HttpServletRequest等;
- 使用的注意事项有哪些,是否用出过什么问题?不需要了需要remove掉。自己在什么业务背景的时候做了一个什么功能用到了它,解决了什么问题,后来出现了一个什么现象,定位到是ThreadLocal的问题;
- 原理是什么?内部维护了一个ThreadLocalMap,key-value如何设计;key是虚引用,强软弱虚引用;value需要remove,否则会内存泄漏;JVM定位内存泄漏问题;
- 其他…:扩展下InheritableThreadLocal、Transmittable-Thread-Local(如果要展开还是同样的流程)
相较于之前的回答,在技术人看来就很专业,一上来就抓住了最难的那部分(说原理),心里想着最难的我都没问题,其他的还能有什么问题?今天想想,也许这就是技术人的狂欢吧。我今天面对的问题是谈谈ThreadLocal的理解,而我要做的是把这个东西说明白,只说原理就说明白了?我认为答案是否定的,起码这不够。
突然想到一些好笑的事情。我没有真实线上调优过JVM,但是那些调优参数、调优分析思路我是张口就来;没有当过架构师,分布式、微服务、DDD设计也能侃侃而谈;没经历过真实的高并发场景,解决高并发、高性能、大数据场景的方法论我倒是知道一堆。所以我认为,我是在抛开背景谈技术,无疑耍流氓。尽管这样的回答会过于正式,但我应该明白能否全面的理解和看待事物,和我是否需要全面的理解和看待事物是两回事。
回顾一年多以前写的文章要是面试官再问我volatile,我就这么答、要是面试官再问我synchronized,我就这么答,当时觉得如果能这么回答,提问的人应该能感受到我的强大的知识储备。今天看来,我的目的应该是达到了(正常,背课文嘛,无非是谁背的多,理解了并记住了),今天要做的就是来个加强版。
同理,请你谈谈ExecutorService、ScheduledExecutorService、CompletableFuture这几个并发工具的理解,完全可以复用前面使用的这个回答流程:
- 它是什么?
- 它解决了什么问题?
- 它怎么解决的这个问题?
- 如何为我们的业务提供帮助?
- 使用的注意事项有哪些,是否用出过什么问题?
- 原理是什么?
- 其他(差异化处理、个性化改造)…
不知道你是否有这样的感觉,按照这个模板的回答方式去回答,但凡你在业务项目中用过,甚至是看到别人用过,并且你对原理的东西有一定了解,我相信你也不会张口就是线程池的7个参数含义。起码我是的。
六、碎碎念
做为一个练习一坤年的B端业务开发,工作中遇到的bug,真心没有因为操作系统这命令和那命令叫什么、谁前谁后导致的,并且遇到了这种太底层的问题,我向来都是反馈领导,毕竟我还有需求排着呢。
不如专注于和别人更好的沟通协作,更高效的工作安排,少写点业务bug,我觉得能做好这些已经很不容易了。而更有条理、更全面的描述问题、分析问题,我觉得是能够帮助我们达成这一目的的,而这就比卷深度更有价值。
当然,我们也还是要具备一定的解决问题的能力。