從上面的圖片咱們能夠看出大體分爲三個部分: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 這些用得不少的,則須要放在前面。
今天也只是簡略地提了一下整個知識體系,後續有空閒時間會繼續慢慢分享相關文章。有興趣的朋友不妨關注一下我,這樣能及時查看後續文章。
以上爲轉載內容,歡迎在評論區討論學習。