从上面的图片咱们能够看出大体分为三个部分:JDK 源码、JVM 原理、框架源码。面试
JDK源码
JDK 源码是一切的基础,许多框架都参考了 JDK 源码的实现思路,所以弄懂 JDK 源码是一件很是重要的事情。而 JDK 源码又能够分为下面 4 大块:数据库
- 集合源码
- 并发集合源码
- 并发包源码
- 阻塞队列源码
- 线程池源码
集合源码
说到集合,咱们你们都很是熟悉,这但是咱们工做中用得很是多的一类 API。但会用了,还得知道它究竟是如何实现的,这样才能够避免踩坑。JDK 源码中的集合并非特别多,大概有 四大类大概 14 个经常使用的 API。数组
List集合缓存
- ArrayList:列表集合经典实现。
- Vector:列表集合经典实现,线程安全,与 ArrayList 对应。
- LinkedList:链表结构的经典实现。
- Stack:栈结构的经典实现,先进后出的数据结构。继承了 Vector,线程安全。
Set集合安全
- HashSet:Set 集合的哈希实现。
- LinkedHashSet:Set 集合的哈希实现,维护了元素插入顺序。
- TreeSet:Set 集合的有序实现。
Queue集合markdown
- PriorityQueue:优先级队列
- LinkedList:双向队列实现
- ArrayDeque:双向循环队列实现
Map集合
- HashMap:Map 集合的经典哈希实现。
- LinkedHashMap:在 HashMap 的基础上,增长了对插入元素的链表维护。
- WeakedHashMap:在 HashMap 的基础上,使强引用变为弱引用。
- TreeMap:Map 集合的有序实现。底层是红黑树的经典实现。
在这 14 个经常使用的 API 中虽然有一些咱们还没使用过,但若是你要创建起一套完整的知识体系,那么仍是有必要去仔细琢磨一下它们的做用,而且对它们进行横向比较的。
并发集合源码
咱们前面说到的集合源码,它们大部分都是线程不安全的,它们在多线程的环境下使用会产生各类各样的问题。而线程安全与并发安全又不同,线程安全考虑的是绝对的安全,而并发安全则是牺牲部分特性来提升并发效率。也就是说并发集合适合在多线程环境下使用,而且效率足够高,可以应对高并发的状况。
在 JDK 的并发集合源码中,一共有 7 个经常使用的并发集合。
- ConcurrentHashMap:高并发的HashMap
- ConcurrentSkipListMap:高并发下的TreeMap(基于跳表实现)
- ConcurrentSkipListSet:内部使用ConcurrentSkipListMap实现
- CopyOnWriteArrayList:高并发的ArrayList,适合读场景。
- CopyOnWriteArraySet:高并发的Set集合,使用CopyOnWriteArrayList实现。
- ConcurrentLinkedQueue:高并发的链表队列。
- ConcurrentLinkedDeque:高并发的双向链表队列。
虽然有 7 个并发集合,可是实际上只有 5 个左右,由于另外两个都直接用代理的方式委托实现。例如:CopyOnWriteArraySet 类内部并无具体的逻辑实现,而是直接委托 CopyOnWriteArrayList 实现。
并发包源码
咱们前面说过许多集合都是线程不安全的,在多线程环境、甚至高并发环境须要使用并发集合。那么并发集合究竟是怎么实现线程安全的呢?在 JDK1.8 以后,并发集合大部分都使用 CAS 来实现线程安全。而其实在 JDK1.8 以前,许多线程安全都是使用锁来实现的。而说到锁,咱们就必须了解一下并发包源码。
并发包源码从零开始定义了一整套实现并发安全的机制,而且还提供了很多方便使用的并发工具。咱们经过并发包就能够很是方便地实现多线程下的线程安全和并发控制,后面说到的阻塞队列都是以这个为基础的。
并发包是一整套接口和实现的定义,其主要的类和实现以下:
在并发源码最顶层的是 AbstractQueueSynchronizer 接口,其定义了并发控制最为基础的几个接口,以后的 Lock、ReentrantLock、ReentrantReadWriteLock 都是在这基础上实现的。而 Condition 接口则是继 AbstractQueueSynchronizer 接口以后的另外一个重要接口,其定义了分支条件,使得并发适用于更复杂的业务。
定义好了 AbstractQueueSynchronizer 和 Condition 接口,并发包的基础就搭建好了。并发包中提供了 CountDownLatch、CyclicBarrier 等并发工具类来实现经常使用的并发操做,这些工具类都是使用前面提到的 Lock 来实现的。
阻塞队列源码
阻塞队列实际上是属于并发包的一部分,但由于其功能性特别明显,因此咱们专门挑出来单独说。阻塞队列用于在高并发环境下进行数据的交换,其实现基础是咱们前面说到的并发包,没有并发包就没有阻塞队列。
在 JDK 中,阻塞队列一共能够分为三大类一共 8 个经常使用的阻塞队列。
基础实现
这块是阻塞队列最基础的实现
- ArrayBlockingQueue:数组组成的有界阻塞队列
- LinkedBlockingQueue:链表组成的无界阻塞队列
- LinkedBlockingDeque:链表组成的双向阻塞队列
有序延迟实现
这块的阻塞队列还实现了元素的排序以及延迟功能,只有时间到了才能出队列。
- PriorityBlockingQueue:支持优先级排序的无界阻塞队列
- DelayQueue:支持优先级实现的无界延迟阻塞队列
- DelayedWorkQueue:线程池中的延迟阻塞队列
数据交换实现
这块阻塞队列主要用于多线程之间的数据交换
- SynchronousQueue:不存储元素的数据交换阻塞队列
- LinkedTransferQueue:链表组成的数据交换无界阻塞队列
线程池源码
线程池也是 JDK 源码中很是重要的一块,妥善利用线程池能够提升效率。而线程池的基础其实就是咱们前面讲到的阻塞队列,线程池的延迟功能都是使用阻塞队列实现的。线程池的总体架构比较多,可是并不复杂,也没有什么难点。若是弄懂了线程池的总体类结构,那么线程池也就没什么太大的问题了。
JVM原理
JVM 能够说是 Java 程序员必需要掌握的基础知识了。初学者或许会搞不懂这些东西到底有什么用,一开始学习都是为了面试用。但老司机告诉你学习 JVM 原理有下面两个很是重要的用处:
- 理解 Java 语言特性。Java 代码写出来的只是语言层面的东西,当咱们要了解一个特性是如何实现的,咱们就须要深刻到字节码层面。例如:boolean 这个类型,在 Java 语言层面是存在的。可是其在字节码层面是不存在的,其在字节码层面是使用 Integer 的 1 和 0 表示 true 和 false。
- 学习排查线上问题。咱们遇到线上 JVM 问题,常常提示说:
OutOfMemoryError: Java heap space
。这时候你会不知道从何入手,这是由于你不懂 JVM 的内存结构。因此你必须去学习 JVM 的内存结构,如何排查问题发生在哪块内存,如何解决问题。而这一切的基础就是 JVM 的基础知识。
关于 JVM 的基础知识,我写了一个系列的文章来介绍,有兴趣的能够阅读如下:JVM系列文章
框架源码
学习完 JDK 的源码,咱们就须要把咱们经常使用的框架源码都弄清楚。这样在遇到框架问题的时候,咱们才能够快速地排查问题。
上面的思惟导图从上到下都是逐次递进的。咱们学习了 JDK 源码,再学习 Web 框架就能够实现简单的 Web 项目。而随着业务增加,咱们须要加入 RPC 服务化框架将其服务化。而随着业务复杂化和井喷,咱们须要加入消息队列和缓存来进一步提升业务的稳定性。
Web框架
Spring 和 MyBatis 能够说是 Java Web 开发者必学的两个框架了,所以对这两个框架有必要作一个深刻的了解。
对于 Spring 来讲,其整个源码体系太过于复杂,因此咱们仍是得抓住重点。对于 Spring 来讲,最重要的是其 AOP 和 IoC 的实现,以及其容器体系和经常使用的接口。而对于 MyBatis 来讲,其体系相对没有 Spring 那么复杂,因此能够稍微深刻一些。
RPC框架
在全部 RPC 框架中,dubbo 能够说是最通用的一个了。因此若是你所在的公司没有自研的 RPC 框架,那么你不妨能够将 dubbo 做为你的学习框架。
对于 RPC 框架来讲,其实无非就是封装对象代理,最后经过与服务提供者进行网络通讯。可是如何进行封装,若是进行负载均衡的实现,这就考验一个框架设计者的功力了。
一致性框架
对于分布式系统,很是重要的一个组件就是一致性框架。在这些框架中,最多见的两个是 Zookeeper 和 Eureka。Zookeeper 实现了 CAP 中的 CP(即注重强一致性),而 Eureka 则是实现了 CAP 中的 AP(即注重可用性)。
虽然日常咱们都将 Zookeeper 和 Eureka 做为服务化的协调组件,基本上没有什么机会深刻学习。可是有机会仍是能够深刻了解一下的。
消息队列
消息队列能够说是实现业务解耦以及突发流量的利器。而在大型业务场景中,最经常使用的就是 Kafka 和 RocketMQ 了,所以弄懂这两个消息队列的原理基本上就足够用了。
对于消息队列,建议先选择一个深刻研究,先弄懂其基本原理,以后再阅读源码验证想法。由于 RocketMQ 是基于 Kafka 改进的,因此建议先从 Kafka 入手研究。Kafka 研究得差很少了,RocketMQ 的研究也会进展飞速。
缓存框架
缓存框架能够说是高并发下必用的一个框架了,但咱们常常只是使用它,而不知道起内部的原理和构造。所以找个时间深刻学习下原理,仍是颇有必要的。
网络框架
对于一些网络项目,例如聊天 IM 等,就须要用到 Netty 等框架。而 Netty 又是这类网络框架的佼佼者,经过对其源码的研究,能够学到很多知识。
搜索框架
对于一些搜索功能的项目,单纯的数据库 SQL 查询已经没法知足需求了,这时候 ElasticSearch 的学习和研究就提上议程了。有时间的话,研究学习一下仍是颇有必要的。
增量订阅框架
Canal 和 Otter 框架能够帮助你得到数据库的变化信息,从而更方便地作业务扩展。对于这类框架,属于特定领域的细分框架,有时间能够研究一下。
总结
做为一个工做了 5 年的开发,上面的知识体系仍是未能彻底消化,只能说是对于部分有些掌握。若是你也想构建本身的知识体系,那么我建议你能够按照我列出的顺序去学习。先研究学习 JDK 源码,以后学习 JVM 原理,最后再去研究学习框架源码。而框架源码的研究也从该框架的经常使用程度排序,对于 ElasticSearch 这类不经常使用的,能够放在后面。而对于 Spring 这些用得不少的,则须要放在前面。
今天也只是简略地提了一下整个知识体系,后续有空闲时间会继续慢慢分享相关文章。有兴趣的朋友不妨关注一下我,这样能及时查看后续文章。
以上为转载内容,欢迎在评论区讨论学习。