大家好,我是不耍嘴皮子,只讲java底层源码课的码炫课堂创始人码哥,全网唯一讲解及手写各大框架及中间件源码的极客,上班之余做源码课只是我的爱好,拯救水深火热中的curder屌丝们才是我的使命!
众所周知,2022年毕业生已达1076万人,不管你是应届的或者非应届,此时此刻这就是与你竞争的庞大人群,请问你的优势在哪里?北大博士去当城管,清大硕士去三,四线城市街道办,人都已经被逼到这个份儿上了。。。
有人说你又在贩卖焦虑了,其实我本无意贩卖焦虑,但是焦虑又是客观存在的,难到我不贩卖焦虑你就不焦虑了吗?在这个人均焦虑的时代,这是每个人都无法逃避而又必须去面对的现实。
有没有人去思考过,我们为什么焦虑?就拿it行业来说,996已是家常便饭,007也不在少数,为什么会这样?归根结底就是因为我们处于全球产业链的低端,我们80%的码农都干着附加值极低的curd的工作。
全球it产业链的分工早已成型,短期内不会改变。
高端产业全在欧美,他们只负责出方案(比如intel,苹果,google等),属于第一梯队。就拿芯片来说,方案下达之后,由台积电,三星等代工厂去集成,这是第二梯队。然后中国,印度等只有使用的份儿,我们只能去做做应用软件,外包软件的份儿,这是第三梯队。
更可恶的是老外把软件框架都写好了,然后你中国,印度拿去用吧,去写写应用吧,高端芯片,高端ic你是摸都别想摸,只能去摸摸软件,然后软件中的框架、中间件你们也别搞了,你们只要curd就行了,这就是全球it产业链的分工。
造成的结果就是我们很卷,人家很舒服,因为人家完成了底层的东西,人家玩的是底层,而我们在应用层玩命卷。
根据28原则,这个世界80%的财富聚集在20%的人手中,任何一个国家或者团体都是一个金字塔,塔尖的永远是20%的精英,屌丝们占了80%。
公司里996的永远都是那80%的屌丝,你见过多少领导在加班的?正所谓curd越熟练,加班越多,脏活儿累活儿全是你的。但是屌丝们却把这个当做一项人前可炫的技能,所以如果你还有一点点智慧的话就应该意识到,curd熟练并不是一项很了不起的技能(如果你不认同请不要再往下看了,请继续做你的屌丝去),curd门槛如此之低,能够取代你的人太多了。
你稍微用脑子想想,连外面的水货培训机构的讲师都是初中毕业,高中毕业,一天大学没上过的,或者大学辍学的,他们这样的照样能给你上curd课,而你们都是正规大学毕业的,难道你们的智商还不如那些割韭菜的?答案肯定不是,只能说明curd的门槛实在是太低太低!
道不同不相为谋,之前我们码炫粉丝群里有好几个杠精说只要会curd就行了,大家都是这样的。你不想想你自己赖着不往前走,还拿着80%的屌丝大众的行为作为自己懒惰的借口。干最多,最脏的活,然后还学不到东西,每天苦逼的加班,最后加到一口老血吐在键盘上,血中还映射着你沧桑的脸,空留脸部上方秃了半顶的为数不多的头发在机房的嘈杂声中凌乱。人间惨剧,无过于此!
讲这么多最终的结论就是卷应用层是远远不够的,应用层不断更新(貌似都是更新的新技术,其实都是在底层技术上的包装),有人却始终看不清这个事实。
所以咱们要做的是以不变应万变,从现在起,将精力转向java底层源码,深挖底层才是王道。
有人起步于curd,也止步于curd,庸庸碌碌到35岁,最后从一个只会curd的小屌丝熬到还是只会curd的老屌丝。屌丝依旧,只是老了而已!
所以卷不是你的错,而是跟你同级别的屌丝太多,本质是你在职场中没有实现越阶,甘愿做那80%的人。
随着大环境的日趋月下,各大互联网公司业务萎缩,已经不再需要那么多社畜去堆积curd功能,自然开始挥舞裁员大刀砍向curder,curder们哀嚎遍野。
大环境不行,高薪不复存在,如果还抱着curd混日子,混到35岁也只是个最底层屌丝,到那时候你的领导都比你岁数小,天天被他吆喝着干这干那,相信稍微有点自尊的都会待不下去,但是你只会curd,即使跳槽了等待你的依然还是被年轻领导虐的份儿。
(注意,是真大佬,培训机构的或者在培训机构呆过的勿扰。众所周知,培训机构的所谓的大佬讲师几乎都是职场混不下去的loser,专骗韭菜的,真大佬是不会去专职讲课的)。
这些框架和中间件都是应用层的基础,出现难以解决的问题通常报错的异常都是从这些底层框架和中间件里跑出来的,所以要解决问题首先得完全熟悉这些底层框架及中间件的源码,所以我们的源码课从最底层的jdk源码开始,确保80%的内容都是手写源码复现。
jdk是整个java生态的基础,也是一个真正的宝藏,尤其是juc,这是doug lea的大作,有人说doug lea对java的贡献一点都不亚于格斯林,这句话一点都没错,没有doug lea的juc就不会有java的高并发,但是你们扪心自问,有多少人把juc的源码都看完的?我敢说没几个,不过这也正常,因为80%的curder都是不重视jdk的,他们只重视微服务啊这些花里胡哨的所谓高新技术。
有价值的东西通常都是无人问津的,没有价值的都是趋之若鹜的,就像屌丝们都喜欢聚集在抖音一样~不做解释,懂的自然懂。
目前正在录制【专题一、jdk源码&多线程&高并发(5个阶段)】,我们已经完成到第3阶段了
下面简单介绍下已经录制完成的内容
第1阶段是 【深入多线程】
先来点面试题感官刺激下吧
多线程部分面试题
1、进程、线程、协程的区别是什么?
2、java实现线程的方式有几种?分别是什么?分别用于什么场景?
3、jvm启动之后大概启动了多少线程?请描述其中常见的5-6个线程,并描述这些线程是干吗的?
4、每天都使用main方法吧,请描述main线程启动及工作原理
5、java线程执行了start方法之后,run方法就自动运行了,请描述其底层原理
6、Thread类的start方法源码看过吗?看过请描述start方法中调用的start0方法的底层原理
7、java线程有哪几种状态?分别描述其状态的含义及各个状态之间是如何转换的
8、能用jni技术手写一个自定义线程吗?如果不能,描述下思路也行。
9、在阅读源码过程中,如果一个java方法是native的,那么你如何找到其对应的c++源码?请描述寻找步骤
10、java方法运行结束了,jvm进程也就结束了,那么请描述下jvm进程销毁原理
11、什么样的接口可以使用lamda表达式表示?
12、假如A公司的一个项目要跟B公司项目联调,A公司的一个线程需要引入B公司提供的jar包,那么如何保证A公司线程的安全性(比如B公司jar包里有恶意代码,有可能会删除A公司服务器上的重要文件)
13、jvm的线程栈容量默认是多大?
14、-Xss大小及单个栈帧的大小对栈深度有什么样的影响?
15、线程优先级设置后如何生效的?运行结果是否遵循设置的优先级运行?为什么?
16、请描述下什么叫守护线程?守护线程和用户线程之间的区别是什么?java中如何设置守护线程?守护线程常见的使用场景有哪些?
17、请简单阐述守护线程自动销毁原理
18、jvm中的DestroyJavaVM线程是否是用户线程?
19、实际项目中用过钩子线程吗?具体如何使用的?使用过程中需要注意什么?
20、请阐述钩子线程的原理
21、请描述4种以上线程处理异常埋点方案,并阐述其优先级
。。。。。
这才是列举出来的一部分,这些面试题80%都是网上没有的,所有的题目几乎都是vip课程里讲的内容。
本阶段课程中详细讲解了Thread类的用法,然后深入到Thread类的源码里(从java一直到jvm的c++代码),另外再说下本阶段课程需要自编译openjdk的,因为课程讲解中我们代码会跟踪到jvm底层c++的源码中去的(自编译openjdk的文档在群文件里),使用的是GDB进行调试的,详细的讲解了Thread类在c++中的原貌,Thread源码在java中并不多,只是一个壳子而已,绝大多数代码都是在c++里,我们还实现了一个自定义的线程MyThread类,在c++代码里实现逻辑,然后回调MyThread中的run方法,从而让大家更彻底的了解Thread。
1-40集都是Thread的内容
接下来是volatile的内容,这部分内容颠覆性的打脸了市面上所谓的大佬一本正经的胡说八道,这些个伪大佬真是误人子弟,害人不浅。
本知识点从一个诡异的案例开始,然后揭秘了可见性的本质问题,然后从cpu多级缓存架构(你如果是真大佬的话就应该知道,应用层的多级缓存架构其实就是抄的底层cpu的多级缓存架构-应用层多级缓存架构里的ehcache就类似cpu多级缓存中的storebuffer,redis就类似于cache,mysql就类似于内存。应用层中的缓存一致性解决方案其实就是抄的MESI协议。所以应用层技术其实一点都不新鲜,都是抄的底层的,所以底层才是王道~懂的自然懂)开始讲,然后到cacheline,MESI协议,内存屏障等。从MESI协议的角度去理解为什么出现可见性问题,通过一个水货讲师讲的美团面试题纠正并揭秘了可见性的本质问题,volatile知识点肝了接近40集,这是全网绝无仅有的。
41-79集都是volatile的内容
接下来是synchronized部分,这部分内容也是从c++层面去给大家分析源码流程,然后通过画图讲解其原理,重头戏是把c++代码逻辑全部都拉出来在java层面实现了一遍,目的是为了让c++基础不太好的同学更容易通过java代码去理解synchronized的原理,这也是全网唯一这么干的(在我们群里我让群里同学在一个月之内,如果在java层面实现synchronized的就送他vip会员的,至今为止才有一个同学写了1/3的代码,但是我也给了会员,因为确实很难,需要实现整个升级过程)
80-126集都是synchronized的内容
接下来就玩的更深了,详细讲解了跟synchronized底层息息相关的三大队列:cxq,entrylist,waitset相关的知识点,同样是从c++层面给大家分析源码,并且通过画图和案例的方式讲解了一个线程进入同步代码块之后是如何在这三大队列里流转的,并且通过案例揭秘了notify方法其实并没有去唤醒线程,它只是去挪动了线程节点而已,interrupt方法其实也没有真正去中断线程,它只是去做了标记位等等。这些都是颠覆大家认知的知识点,大家平时如果不注意的话,很容易出错。
127-146集都是跟synchronized相关的底层三大队列相关的知识点
阶段1的最后一部分内容是线程池系列,这个系列先是画图讲解线程池原理,然后通过手写一个线程池来实现其原理,最后又分析了juc中的线程池的源码,最后揭秘美团的线程池组件是怎么玩的(完成了部分代码)
147-179集都是线程池相关的内容
以上是第一阶段的内容,接着进入第二阶段
第2阶段是 【深入多线程设计模式】
这一阶段内容非常重要,本阶段内容是第三阶段juc的理论基础,如果没有这一阶段的讲解,你直接玩juc的话是玩不转的,juc部分相当于是实践,理论指导实践,没有理论的指导,你学习juc就会像没头的苍蝇一样乱撞,学不得法,事倍功半!
本阶段的内容全部在这里,我就不一一介绍了。
最后是第三阶段的内容
第3阶段是 【深入juc源码解析并手写】
这里要强调手写,本阶段的内容80%的源码都是通过手写复现的,可以说是几乎复现了每个类核心方法,一行一行的手写并画图讲解,也可以说是全网唯一的。
光一个ConcurrentHashMap的内容就肝了67集,这也是全网绝版,这里面有很多知识点,比如寄生读写锁等知识点,都是外面培训机构从未讲解过的,很多同学也都是第一次听到,目前整理了StampedLock和ConcurrentHashMap的面试题,来感官刺激下吧!
保证你从未见过的ConcurrentHashMap面试题:
ConcurrentHashMap面试题
1、如何找到大于一个数的最小2的幂?比如大于5的最小2的幂就是8,大于7的最小2的幂也是8,大于9的最小2的幂是16,请列举2种方法。
2、简述ConcurrentHashMap中hash扰动的原理,为什么要扰动?
3、hashmap的hash扰动为什么比ConcurrentHashMap少了一个 “&HASH_BITS”?
4、ConcurrentHashMap中sizeCtl字段的含义,下面哪个说法是错误的?
1)、默认为0,用来控制table的初始化和扩容操作
2)、-1 代表table正在初始化
3)、-N 表示有N-1个线程正在进行扩容操作
4)、如果table未初始化,表示table需要初始化的大小。
5)、如果table初始化完成,表示table的容量,默认是table大小的0.75倍
5、ConcurrentHashMap在初始化的时候是如何控制多线程安全性的?
6、ConcurrentHashmap容量为什么要设置成2的幂次方?
7、ConcurrentHashMap在扩容的时候sizeCtl是一个非-1的负值,如何得来的?
8、ConcurrentHashmap的红黑树的binCount未什么固定为2?
9、ConcurrentHashmap最多允许多少线程同时参与扩容?
10、ConcurrentHashmap扩容前计数在高并发时为什么效率很高?
11、ConcurrentHashmap每个线程都会参与扩容吗?如果不是,那么参与扩容的线程的条件是什么?
12、ConcurrentHashmap参与扩容的线程至少负责多少个哈希桶的迁移?
13、ConcurrentHashmap多线程下分配迁移任务是如何保证安全性分配的?
14、ConcurrentHashmap迁移时普通链表是如何迁移的?
15、ConcurrentHashmap迁移时红黑树是如何迁移的?
16、ConcurrentHashmap链表转树的时候为什么要同时维护一个双向链表?
17、ConcurrentHashmap某个哈希桶迁移之后分离为高桶和低桶,请问高桶和低桶之间的间距为什么是原来table的长度?
18、话说假如有32个线程并发,ConcurrentHashMap的执行效率大概是hashtable的几倍?
19、ConcurrentHashmap某个哈希桶迁移之后分离为高桶和低桶,有没有可能所有节点都在高桶位置或者都在低桶位置?
20、ConcurrentHashMap在查询的时候有没有并发问题?如果有,具体是什么问题?
21、ConcurrentHashMap在迁移的时候,如果读线程正在执行get操作,此时有什么影响?
22、ConcurrentHashMap的红黑树在新增后调整平衡的时候,get操作能查吗?为什么?
23、通常读写锁都有写-写竞争,读-写竞争,读-读不竞争这3个特性,那么ConcurrentHashMap的寄生读写锁不具备哪个特性?为什么?
24、ConcurrentHashMap的TreeBin节点为什么还要维护一个寄生读写锁?
25、ConcurrentHashMap中的寄生读写锁,当读线程发现有线程在等待时为什么走链表查找而不走红黑树查找?
26、ConcurrentHashMap扩容迁移之后,原map上的节点最后都被垃圾回收了吗?如果不是,那么哪些没有被回收?
27、ConcurrentHashMap红黑树迁移后,树居然消失了,在什么情况下会消失??
28、ConcurrentHashMap在迁移时lastRun指针所起的作用是什么?
29、ConcurrentHashMap红黑树新增节点时对应到双向链表上是头插还是尾插?
30、红黑树上删除节点时为什么ConcurrentHashMap不采用treeMap的替换值的方式而是采用替换节点的方式?
31、ConcurrentHashmap某个哈希桶迁移时如何确定其在新map中的位置?
32、ConcurrentHashmap红黑树迁移时反树化的条件是什么?
33、ConcurrentHashmap迁移时假如哈希桶上是链表,那么构造高低桶链表时采用头插还是尾插?
34、ConcurrentHashmap迁移时假如哈希桶上是红黑树,那么构造高低桶链表时采用头插还是尾插?
35、jdk8的ConcurrentHashmap里有哪些bug?
36、spring三级缓存中是如何使用ConcurrentHashMap的?
未完,待续
所有的课程讲解都配有图示,图示链接在思维导图里,下面的是上课边讲边画的ConcurrentHashMap的图示:
保证你从未见过的StampedLock面试题
StampedLock面试题
1、相比较读写锁,StampedLock有哪些特性?它是如何解决读写锁的写饥饿问题的?
2、StampedLock中有哪些数据结构?
3、StampedLock是用state变量来区分读锁和写锁的,请问具体是如何区分的?state变量是64位,64个bit位分别表示什么?state默认值时的bit位表示什么?
4、StampedLock的state变量转化为二进制后是 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 1100 0000,请问StampedLock中的读写锁状况是合法的吗?
5、StampedLock的state= 0000 0000 0000 0000 0000 0011 1000 0000 请问经历了几次写锁加锁和释放??
6、请详细描述下StampedLock加写锁的具体流程
7、请详细描述下StampedLock加读锁的具体流程
8、StampedLock中如果线程抢不到锁则进入队列,那么进入队列后会立即就阻塞吗?如果不是,那么入队后会做什么?
9、StampedLock中任何线程都有资格去自旋抢锁吗?如果不是,哪些线程有资格去自旋抢锁?为什么要有这个机制?
10、StampedLock的state变量中如果读锁溢出了,此时如何处理的?
11、StampedLock中线程抢不到锁进入阻塞之前是入队还是入栈呢?在什么情况下是入队?在什么情况下是入栈?
12、StampedLock栈上节点如果被唤醒,唤醒速度是快还是慢?为什么?如果慢原因是什么?如果快,原因又是什么?
13、StampedLock的cancelledWaiter方法中为什么没有prev指针没有跨过CANCELLED状态的节点,而只有next的指针跨过了?
未完,待续
所有阶段3的内容全部在下面,课上的原理讲解画图我就不截了,整个juc的内容其实非常多,你们在外面所看到的课程也最多讲了1/10的皮毛内容。