五年Java程序員該掌握的技術點,這些都不懂,還想拿高薪嗎?

本人不才,呆的廠不算大,工作五年,不過一路走來磕磕碰碰,但總算有了自己的一點小體會。對於一個 Java 開發人員來說,到了 5 年的關鍵節點,需要掌握哪些知識點呢?經過我自己的總結,我列出了下面的思維導圖。

從上面的圖片我們可以看出大致分爲三個部分: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集合

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:Javaheap space。這時候你會不知道從何入手,這是因爲你不懂 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 年的開發,上面的知識體系還是未能完全消化,只能說是對於部分有些掌握。

那麼重頭戲來了,更全的架構師體系圖也爲你準備好了。

架構師築基我不再做闡述,上文已經描述了。

框架學習

程序員每天都和代碼打交道。經過數年的基礎教育和職業培訓,大部分程序員都會「寫」代碼,或者至少會抄代碼和改代碼。但是,會讀代碼的並不在多數,會讀代碼又真正讀懂一些大項目的源碼的,少之又少。這種怪狀,真要追究起來,怪不得程序員這個羣體本身 —— 它是兩個原因造成的。

我們所有的教育和培訓都在強調怎麼寫代碼,並沒有教大家如何讀代碼

大多數工作場景都是一個蘿蔔一個坑,我們只需要瞭解一個系統的局部便能開展工作,讀不相干的代碼,似乎沒用

但是這樣會有三個壞處:

前輩們踩過的坑,總結的經驗教訓,你都不得不親自用最慢的法子一點點試着踩一遍。

很容易養成 stackoverflow driven 的寫代碼習慣 —— 遇到不知如何寫的代碼,從網上找現成的答案,找個高票的複製粘貼改吧改吧,湊活着完成功能再說。寫代碼的過程中遇到問題,開啓調試模式,要麼設置無數斷點一步步跟蹤,要麼到處打印信息試圖爲滿是窟窿的代碼打上補丁,導致整個寫代碼的過程是一部調代碼的血淚史。

你周圍最強的那個工程師的開發水平的上限就是你的上限。

分佈式,高性能架構,大廠必備

分佈式怎麼來的。傳統的電信、銀行業,當業務量大了之後,普通服務器CPU/IO/網絡到了100%,請求太慢怎麼辦?最直接的做法,升級硬件,反正也不缺錢,IBM小型機,大型機,採購了堆硬件。

但是互聯網不能這麼幹,互聯網沒有那麼財大氣粗,還有很多初創,能不能賺錢還不知道。所以就有了軟件方面的解決方案:分佈式系統,簡單說,就是一臺服務器不行,我用兩臺、10臺、100臺...這就要軟件系統需要支持。

那麼多臺機器,我如何讓他們協同工作,這就需要一個調度中心(或註冊中心);肯定涉及到機器間通信,那麼需要一個高效的RPC框架;一個請求過來了,如何分發,需要一個請求分發系統(負載均衡);然後還要考慮每個角色都不能成爲性能瓶頸;還有要能方便的進行橫向擴展,還有考慮單節點故障。

需要分佈式系統,併發量肯定不低,

那麼有了上面的還是不夠的,還需要考慮cache、mq、job、db等方面的問題。cache,現在第三方緩存也比較成熟,redis/memcache等;mq,rabbitmq,kafka等等也不錯;job,現在第三方任務框架有elasticjob和tbschedule,或者你用quartz也支持分佈式環境下的任務,不過quartz就沒有運維工具了。DB,數據庫最好在項目前期就考慮好業務拆分,系統拆分後DB對應的垂直拆分,後期可做讀寫分離,一主多從,甚至多主多從,業界也有了相應的解決方案。

​微服務都不掌握,還敢說自己是架構師嗎?

微服務(Microservice)這個概念是2012年出現的,作爲加快Web和移動應用程序開發進程的一種方法,2014年開始受到各方的關注,而2015年,可以說是微服務的元年;

越來越多的論壇、社區、blog以及互聯網行業巨頭開始對微服務進行討論、實踐,可以說這樣更近一步推動了微服務的發展和創新。

微服務架構(Microservice Architecture)是一種架構概念,旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦。你可以將其看作是在架構層次而非獲取服務的

類上應用很多SOLID原則。微服務架構是個很有趣的概念,它的主要作用是將功能分解到離散的各個服務當中,從而降低系統的耦合性,並提供更加靈活的服務支持。

概念:把一個大型的單個應用程序和服務拆分爲數個甚至數十個的支持微服務,它可擴展單個組件而不是整個的應用程序堆棧,從而滿足服務等級協議。

定義:圍繞業務領域組件來創建應用,這些應用可獨立地進行開發、管理和迭代。在分散的組件中使用雲架構和平臺式部署、管理和服務功能,使產品交付變得更加簡單。

本質:用一些功能比較明確、業務比較精練的服務去解決更大、更實際的問題。

歡迎做Java的工程師朋友們加入Java架構解析:923116658

羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章