首页 课程 师资 教程 报名

Java知识点:JDK源码、JVM原理、框架源码

  • 2019-08-29 14:03:49
  • 3400次 动力节点

  从下面的图片我们可以看出大致分为三个部分:JDK源码、JVM原理、框架源码。

image.png

  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集合

  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之前,许多线程安全都是使用锁来实现的。而说到锁,我们就必须了解一下并发包源码。

  并发包源码从零开始定义了一整套实现并发安全的机制,并且还提供了不少方便使用的并发工具。我们通过并发包就可以非常方便地实现多线程下的线程安全和并发控制,后面说到的阻塞队列都是以这个为基础的。

  并发包是一整套接口和实现的定义,其主要的类和实现如下:

image.png

  在并发源码最顶层的是AbstractQueueSynchronizer接口,其定义了并发控制最为基础的几个接口,之后的Lock、ReentrantLock、ReentrantReadWriteLock都是在这基础上实现的。而Condition接口则是继AbstractQueueSynchronizer接口之后的另一个重要接口,其定义了分支条件,使得并发适用于更复杂的业务。

  定义好了AbstractQueueSynchronizer和Condition接口,并发包的基础就搭建好了。并发包中提供了CountDownLatch、CyclicBarrier等并发工具类来实现常用的并发操作,这些工具类都是使用前面提到的Lock来实现的。

  阻塞队列源码

  阻塞队列其实是属于并发包的一部分,但因为其功能性特别明显,所以我们专门挑出来单独说。阻塞队列用于在高并发环境下进行数据的交换,其实现基础是我们前面说到的并发包,没有并发包就没有阻塞队列。

  在JDK中,阻塞队列一共可以分为三大类一共8个常用的阻塞队列。

  基础实现

  这块是阻塞队列最基础的实现

  ArrayBlockingQueue:数组组成的有界阻塞队列

  LinkedBlockingQueue:链表组成的无界阻塞队列

  LinkedBlockingDeque:链表组成的双向阻塞队列

  有序延迟实现

  这块的阻塞队列还实现了元素的排序以及延迟功能,只有时间到了才能出队列。

  PriorityBlockingQueue:支持优先级排序的无界阻塞队列

  DelayQueue:支持优先级实现的无界延迟阻塞队列

  DelayedWorkQueue:线程池中的延迟阻塞队列

  数据交换实现

  这块阻塞队列主要用于多线程之间的数据交换

  SynchronousQueue:不存储元素的数据交换阻塞队列

  LinkedTransferQueue:链表组成的数据交换无界阻塞队列

image.png

  线程池源码

  线程池也是JDK源码中非常重要的一块,妥善利用线程池可以提高效率。而线程池的基础其实就是我们前面讲到的阻塞队列,线程池的延迟功能都是使用阻塞队列实现的。线程池的整体架构比较多,但是并不复杂,也没有什么难点。如果弄懂了线程池的整体类结构,那么线程池也就没什么太大的问题了。

image.png

  JVM原理

  JVM可以说是Java程序员必须要掌握的基础知识了。初学者或许会搞不懂这些东西到底有什么用,一开始学习都是为了面试用。但老司机告诉你学习JVM原理有下面两个非常重要的用处:

  理解Java语言特性。Java代码写出来的只是语言层面的东西,当我们要了解一个特性是如何实现的,我们就需要深入到字节码层面。例如:boolean这个类型,在Java语言层面是存在的。但是其在字节码层面是不存在的,其在字节码层面是使用Integer的1和0表示true和false。

  学习排查线上问题。我们遇到线上JVM问题,经常提示说:OutOfMemoryError:Javaheapspace。这时候你会不知道从何入手,这是因为你不懂JVM的内存结构。所以你必须去学习JVM的内存结构,如何排查问题发生在哪块内存,如何解决问题。而这一切的基础就是JVM的基础知识。

  关于JVM的基础知识,我写了一个系列的文章来介绍,有兴趣的可以阅读以下:JVM系列文章

  框架源码

  学习完JDK的源码,我们就需要把我们常用的框架源码都弄清楚。这样在遇到框架问题的时候,我们才可以快速地排查问题。

image.png

  上面的思维导图从上到下都是逐次递进的。我们学习了JDK源码,再学习Web框架就可以实现简单的Web项目。而随着业务增长,我们需要加入RPC服务化框架将其服务化。而随着业务复杂化和井喷,我们需要加入消息队列和缓存来进一步提高业务的稳定性。

  Web框架

  Spring和MyBatis可以说是JavaWeb开发者必学的两个框架了,因此对这两个框架有必要做一个深入的了解。

  对于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框架可以帮助你获得数据库的变化信息,从而更方便地做业务扩展。对于这类框架,属于特定领域的细分框架,有时间可以研究一下。

  最后福利,免费赠送免费Java视频教程,登录动力节点官网【视频课程】站内视频可免费下载学习。

image.png

选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交