從下面的圖片我們可以看出大致分為三個部分:JDK源碼、JVM原理、框架源碼。
JDK源碼
JDK源碼是一切的基礎(chǔ),許多框架都參考了JDK源碼的實現(xiàn)思路,因此弄懂JDK源碼是一件非常重要的事情。而JDK源碼又可以分為下面4大塊:
集合源碼
并發(fā)集合源碼
并發(fā)包源碼
阻塞隊列源碼
線程池源碼
集合源碼
說到集合,我們大家都非常熟悉,這可是我們工作中用得非常多的一類API。但會用了,還得知道它到底是如何實現(xiàn)的,這樣才可以避免踩坑。JDK源碼中的集合并不是特別多,大概有四大類大概14個常用的API。
List集合
ArrayList:列表集合經(jīng)典實現(xiàn)。
Vector:列表集合經(jīng)典實現(xiàn),線程安全,與ArrayList對應(yīng)。
linkedList:鏈表結(jié)構(gòu)的經(jīng)典實現(xiàn)。
Stack:棧結(jié)構(gòu)的經(jīng)典實現(xiàn),先進后出的數(shù)據(jù)結(jié)構(gòu)。繼承了Vector,線程安全。
Set集合
HashSet:Set集合的哈希實現(xiàn)。
linkedHashSet:Set集合的哈希實現(xiàn),維護了元素插入順序。
TreeSet:Set集合的有序?qū)崿F(xiàn)。
Queue集合
PriorityQueue:優(yōu)先級隊列
linkedList:雙向隊列實現(xiàn)
ArrayDeque:雙向循環(huán)隊列實現(xiàn)
Map集合
HashMap:Map集合的經(jīng)典哈希實現(xiàn)。
linkedHashMap:在HashMap的基礎(chǔ)上,增加了對插入元素的鏈表維護。
WeakedHashMap:在HashMap的基礎(chǔ)上,使強引用變?yōu)槿跻谩?/p>
TreeMap:Map集合的有序?qū)崿F(xiàn)。底層是紅黑樹的經(jīng)典實現(xiàn)。
在這14個常用的API中雖然有一些我們還沒使用過,但如果你要建立起一套完整的知識體系,那么還是有必要去仔細琢磨一下它們的作用,并且對它們進行橫向比較的。
并發(fā)集合源碼
我們前面說到的集合源碼,它們大部分都是線程不安全的,它們在多線程的環(huán)境下使用會產(chǎn)生各種各樣的問題。而線程安全與并發(fā)安全又不一樣,線程安全考慮的是絕對的安全,而并發(fā)安全則是犧牲部分特性來提高并發(fā)效率。也就是說并發(fā)集合適合在多線程環(huán)境下使用,并且效率足夠高,能夠應(yīng)對高并發(fā)的情況。
在JDK的并發(fā)集合源碼中,一共有7個常用的并發(fā)集合。
ConcurrentHashMap:高并發(fā)的HashMap
ConcurrentSkipListMap:高并發(fā)下的TreeMap(基于跳表實現(xiàn))
ConcurrentSkipListSet:內(nèi)部使用ConcurrentSkipListMap實現(xiàn)
CopyOnWriteArrayList:高并發(fā)的ArrayList,適合讀場景。
CopyOnWriteArraySet:高并發(fā)的Set集合,使用CopyOnWriteArrayList實現(xiàn)。
ConcurrentlinkedQueue:高并發(fā)的鏈表隊列。
ConcurrentlinkedDeque:高并發(fā)的雙向鏈表隊列。
雖然有7個并發(fā)集合,但是實際上只有5個左右,因為另外兩個都直接用代理的方式委托實現(xiàn)。例如:CopyOnWriteArraySet類內(nèi)部并沒有具體的邏輯實現(xiàn),而是直接委托CopyOnWriteArrayList實現(xiàn)。
并發(fā)包源碼
我們前面說過許多集合都是線程不安全的,在多線程環(huán)境、甚至高并發(fā)環(huán)境需要使用并發(fā)集合。那么并發(fā)集合到底是怎么實現(xiàn)線程安全的呢?在JDK1.8之后,并發(fā)集合大部分都使用CAS來實現(xiàn)線程安全。而其實在JDK1.8之前,許多線程安全都是使用鎖來實現(xiàn)的。而說到鎖,我們就必須了解一下并發(fā)包源碼。
并發(fā)包源碼從零開始定義了一整套實現(xiàn)并發(fā)安全的機制,并且還提供了不少方便使用的并發(fā)工具。我們通過并發(fā)包就可以非常方便地實現(xiàn)多線程下的線程安全和并發(fā)控制,后面說到的阻塞隊列都是以這個為基礎(chǔ)的。
并發(fā)包是一整套接口和實現(xiàn)的定義,其主要的類和實現(xiàn)如下:
在并發(fā)源碼最頂層的是AbstractQueueSynchronizer接口,其定義了并發(fā)控制最為基礎(chǔ)的幾個接口,之后的Lock、ReentrantLock、ReentrantReadWriteLock都是在這基礎(chǔ)上實現(xiàn)的。而Condition接口則是繼AbstractQueueSynchronizer接口之后的另一個重要接口,其定義了分支條件,使得并發(fā)適用于更復(fù)雜的業(yè)務(wù)。
定義好了AbstractQueueSynchronizer和Condition接口,并發(fā)包的基礎(chǔ)就搭建好了。并發(fā)包中提供了CountDownLatch、CyclicBarrier等并發(fā)工具類來實現(xiàn)常用的并發(fā)操作,這些工具類都是使用前面提到的Lock來實現(xiàn)的。
阻塞隊列源碼
阻塞隊列其實是屬于并發(fā)包的一部分,但因為其功能性特別明顯,所以我們專門挑出來單獨說。阻塞隊列用于在高并發(fā)環(huán)境下進行數(shù)據(jù)的交換,其實現(xiàn)基礎(chǔ)是我們前面說到的并發(fā)包,沒有并發(fā)包就沒有阻塞隊列。
在JDK中,阻塞隊列一共可以分為三大類一共8個常用的阻塞隊列。
基礎(chǔ)實現(xiàn)
這塊是阻塞隊列最基礎(chǔ)的實現(xiàn)
ArrayBlockingQueue:數(shù)組組成的有界阻塞隊列
linkedBlockingQueue:鏈表組成的無界阻塞隊列
linkedBlockingDeque:鏈表組成的雙向阻塞隊列
有序延遲實現(xiàn)
這塊的阻塞隊列還實現(xiàn)了元素的排序以及延遲功能,只有時間到了才能出隊列。
PriorityBlockingQueue:支持優(yōu)先級排序的無界阻塞隊列
DelayQueue:支持優(yōu)先級實現(xiàn)的無界延遲阻塞隊列
DelayedWorkQueue:線程池中的延遲阻塞隊列
數(shù)據(jù)交換實現(xiàn)
這塊阻塞隊列主要用于多線程之間的數(shù)據(jù)交換
SynchronousQueue:不存儲元素的數(shù)據(jù)交換阻塞隊列
linkedTransferQueue:鏈表組成的數(shù)據(jù)交換無界阻塞隊列
線程池源碼
線程池也是JDK源碼中非常重要的一塊,妥善利用線程池可以提高效率。而線程池的基礎(chǔ)其實就是我們前面講到的阻塞隊列,線程池的延遲功能都是使用阻塞隊列實現(xiàn)的。線程池的整體架構(gòu)比較多,但是并不復(fù)雜,也沒有什么難點。如果弄懂了線程池的整體類結(jié)構(gòu),那么線程池也就沒什么太大的問題了。
JVM原理
JVM可以說是Java程序員必須要掌握的基礎(chǔ)知識了。初學(xué)者或許會搞不懂這些東西到底有什么用,一開始學(xué)習(xí)都是為了面試用。但老司機告訴你學(xué)習(xí)JVM原理有下面兩個非常重要的用處:
理解Java語言特性。Java代碼寫出來的只是語言層面的東西,當我們要了解一個特性是如何實現(xiàn)的,我們就需要深入到字節(jié)碼層面。例如:boolean這個類型,在Java語言層面是存在的。但是其在字節(jié)碼層面是不存在的,其在字節(jié)碼層面是使用Integer的1和0表示true和false。
學(xué)習(xí)排查線上問題。我們遇到線上JVM問題,經(jīng)常提示說:OutOfMemoryError:Javaheapspace。這時候你會不知道從何入手,這是因為你不懂JVM的內(nèi)存結(jié)構(gòu)。所以你必須去學(xué)習(xí)JVM的內(nèi)存結(jié)構(gòu),如何排查問題發(fā)生在哪塊內(nèi)存,如何解決問題。而這一切的基礎(chǔ)就是JVM的基礎(chǔ)知識。
關(guān)于JVM的基礎(chǔ)知識,我寫了一個系列的文章來介紹,有興趣的可以閱讀以下:JVM系列文章
框架源碼
學(xué)習(xí)完JDK的源碼,我們就需要把我們常用的框架源碼都弄清楚。這樣在遇到框架問題的時候,我們才可以快速地排查問題。
上面的思維導(dǎo)圖從上到下都是逐次遞進的。我們學(xué)習(xí)了JDK源碼,再學(xué)習(xí)Web框架就可以實現(xiàn)簡單的Web項目。而隨著業(yè)務(wù)增長,我們需要加入RPC服務(wù)化框架將其服務(wù)化。而隨著業(yè)務(wù)復(fù)雜化和井噴,我們需要加入消息隊列和緩存來進一步提高業(yè)務(wù)的穩(wěn)定性。
Web框架
Spring和MyBatis可以說是JavaWeb開發(fā)者必學(xué)的兩個框架了,因此對這兩個框架有必要做一個深入的了解。
對于Spring來說,其整個源碼體系太過于復(fù)雜,所以我們還是得抓住重點。對于Spring來說,最重要的是其AOP和IoC的實現(xiàn),以及其容器體系和常用的接口。而對于MyBatis來說,其體系相對沒有Spring那么復(fù)雜,所以可以稍微深入一些。
RPC框架
在所有RPC框架中,dubbo可以說是最通用的一個了。所以如果你所在的公司沒有自研的RPC框架,那么你不妨可以將dubbo作為你的學(xué)習(xí)框架。
對于RPC框架來說,其實無非就是封裝對象代理,最后通過與服務(wù)提供者進行網(wǎng)絡(luò)通信。但是如何進行封裝,如果進行負載均衡的實現(xiàn),這就考驗一個框架設(shè)計者的功力了。
一致性框架
對于分布式系統(tǒng),非常重要的一個組件就是一致性框架。在這些框架中,最常見的兩個是Zookeeper和Eureka。Zookeeper實現(xiàn)了CAP中的CP(即注重強一致性),而Eureka則是實現(xiàn)了CAP中的AP(即注重可用性)。
雖然平常我們都將Zookeeper和Eureka作為服務(wù)化的協(xié)調(diào)組件,基本上沒有什么機會深入學(xué)習(xí)。但是有機會還是可以深入了解一下的。
消息隊列
消息隊列可以說是實現(xiàn)業(yè)務(wù)解耦以及突發(fā)流量的利器。而在大型業(yè)務(wù)場景中,最常用的就是Kafka和RocketMQ了,因此弄懂這兩個消息隊列的原理基本上就足夠用了。
對于消息隊列,建議先選擇一個深入研究,先弄懂其基本原理,之后再閱讀源碼驗證想法。因為RocketMQ是基于Kafka改進的,所以建議先從Kafka入手研究。Kafka研究得差不多了,RocketMQ的研究也會進展飛速。
緩存框架
緩存框架可以說是高并發(fā)下必用的一個框架了,但我們經(jīng)常只是使用它,而不知道起內(nèi)部的原理和構(gòu)造。因此找個時間深入學(xué)習(xí)下原理,還是很有必要的。
網(wǎng)絡(luò)框架
對于一些網(wǎng)絡(luò)項目,例如聊天IM等,就需要用到Netty等框架。而Netty又是這類網(wǎng)絡(luò)框架的佼佼者,通過對其源碼的研究,可以學(xué)到不少知識。
搜索框架
對于一些搜索功能的項目,單純的數(shù)據(jù)庫SQL查詢已經(jīng)無法滿足需求了,這時候ElasticSearch的學(xué)習(xí)和研究就提上議程了。有時間的話,研究學(xué)習(xí)一下還是很有必要的。
增量訂閱框架
Canal和Otter框架可以幫助你獲得數(shù)據(jù)庫的變化信息,從而更方便地做業(yè)務(wù)擴展。對于這類框架,屬于特定領(lǐng)域的細分框架,有時間可以研究一下。
最后福利,免費贈送免費Java視頻教程,登錄長沙牛耳教育官網(wǎng)【視頻課程】站內(nèi)視頻可免費下載學(xué)習(xí)。