目錄
學習的知識體系圖片太大,直接奉上鍊接,可以自己保存到電腦上:https://blog.csdn.net/qq_43040688/article/details/105819866
這些全部都是博主學習時記錄的一些筆記,手上也有學習時使用的相關的網課資源或者是課本資源,感覺講的都很不錯,資料也很全。
可以在文章底下評論,我會私信聯繫你,如果覺得資源不錯,可以爲這篇文章點個贊
,讓更多的人可以看到~~
一. 數據庫
1.1 關係型數據庫
MySQL(已更新)
推薦書目:《MySQL必知必會》、《MySQL技術內幕》、《高性能MySQL》
對於MySQL語法優先學習SQL的語句增刪改查等,然後在LeetCode練習一下數據庫的題目,可能會手寫SQL語句
接着需要重點學習索引、鎖、事務、SQL優化以及MySQL的架構
1.2 非關係型數據庫
Redis
二、Java基礎
2.1 Java虛擬機(已更新)
虛擬機推薦 《深入理解Java虛擬機》 這本書,重點學習一下內存
、垃圾回收
、類加載機制
這幾部分內容。
2.2 Java併發(已更新)
Java併發主要看了汪文君的併發三個階段,內容比較豐富,看了很久
Java併發基礎
學習Java併發,需要先掌握線程的一些基礎知識
這些基礎知識的組合構成了後面的設計模式
- 首先應該瞭解如何啓動一個多線程,即使用Runnable、Callable、Thread;還需要了解線程啓動後的生命週期,瞭解了不用實現方式的差別,最重要的研讀Thread的源碼,詳情參考:
Java多線程起步
,Thread構造函數源碼分析
- 需要學習Thread常用API以及三種關閉線程的方式,詳情參考:
Thread的API
- 需要了解this鎖和class鎖,詳情參考:
Java多線程之認識“鎖”
- 需要了解線程間的通訊,最基本的就是消費者和生產者模型,需要深入瞭解了wait、sleep、notify、nitifyAll的機制和差異,對於wait set要有個清晰的認識,詳情參考:
Java多線程之線程間的通訊
- 需要嘗試自定義了一個Boolean鎖,瞭解了加鎖和釋放鎖的過程,實現了獲取正在阻塞的線程;需要了解線程運行時出現異常的處理方式
,詳情參考:自定義Boolean鎖&捕獲線程中的異常
- 需要學習了線程組的概念以及常用API,如interrupt,setDaemon,activeCount,enumerate, 詳情參考:
線程組
- 需要自定義了一個線程池,對線程池的處理機制有了較深的理解,詳情參考:
自定義線程池
多線程的設計模式
Java在併發的場景中,設計模式就像個套路,開發者可以自由的組合以滿足應用需求
下面有十四個多線程的設計模式,幫助理解後面的JUC包。
-
第一個設計模式是:觀察者模式。需要定義一個主題,一個觀察者。主題在多線程情況下,可以實現Runnable接口,傳遞給線程;線程在執行的過程中,可能會修改主題的狀態;主題狀態發生變化,會通知觀察者,執行觀察者的onChange方法。詳情參考:
觀察者模式
-
第二個設計模式是:單例模式。解決方式有三種:第一種是double check方式,但是可能會引起空指針異常;第二種是holder方式,利用內部static 類實現;第三種是利用enum類實現。詳情參考:
單例模式
-
第三個設計模式是單線程執行模式。就是在同一時刻只能有一個對共享資源進行操作。詳情參考:
單線程執行設計模式
-
第四個設計模式不可變對象設計模式。是一種無鎖的設計模式,其思想是如果共享資源是不可以修改的,則線程一定安全。詳情參考:
不可變對象設計模式
-
第五個設計模式確保掛起設計模式。當線程在工作時,如果來了其他任務,將任務放入到隊列中等待。詳情參考:
確保掛起設計模式
-
第六個設計模式Balking設計模式。當工作已經執行過了,就直接return,防止重複的工作,提高效率。詳情參考:
Balking設計模式
-
第七個設計模式生產者-消費者設計模式。如果生產一個產品,放到吧檯上,通知消費者;如果吧檯上有產品,消費者就會立即執行。詳情參考:
生產者-消費者設計模式
-
第七個設計模式讀寫鎖的設計模式。讀取操作與讀取操作之間不存在線程安全的問題,所以在此情況下,避免加鎖,影響性能。詳情參考:
讀寫鎖的設計模式
-
第八個設計模式Thread-Per-Message。每一個請求都創建一個線程服務,爲了提高性能,可以使用線程池。詳情參考:
Thread-Per-Message
-
第九個設計模式 Worker 設計模式。需要一個Master,負責創建worker、啓動worker、監控worker以及接受任務。
詳情參考:Worker 設計模式
-
第十個設計模式Future設計模式。通過返回一個票據,避免陷入阻塞;當任務完成後,可以調用票據的get方法獲取結果。詳情參考:
Future設計模式
-
第十一個設計模式兩階段終止設計模式。當線程關閉時,不會立馬關閉,而是先執行第二階段的資源釋放任務。利用的try…finally…。詳情參考:
兩階段終止設計模式
-
第十二個設計模式線程保險箱設計模式。利用Map,線程是key,數據是value。可以保證線程間的數據是安全的。需要注意:線程池下,需要清空原來的數據。詳情參考:
線程保險箱設計模式
和上下文設計模式
-
第十三個設計模式Active Objects 設計模式。接受異步調用的主動方法。可以主動異步的執行一些任務。詳情參考:
Active Objects 設計模式
-
第十四個設計模式Count Down設計模式。多個子任務執行,主任務等待子任務全部執行完,再執行詳情參考:
Count Down設計模式
Java高併發與JVM的關係
主要是學習
wait set
、JMM模型
JMM模型中有四個內容,主要參看博客:Java多線程之內存模型三大特性
。如果想學習更多,請學習JVM的部分。
- 解決高速緩存中數據不一致性的問題——總線鎖(效率低)、高速緩存一致性協議,英特爾
- 高併發的三個要求——原子性、可見性、有序性
- happens-before
- 指令重排序
Java多線程之內存模型三大特性:https://blog.csdn.net/qq_43040688/article/details/105823532
原子包
CAS :
- 樂觀鎖,CompareAndSwap。
- 優點是:保證變量的原子性;避免從用戶態到內核態,可以提高性能確定。
- 缺點:在競爭激烈的情況下,浪費CUP資源。
- 還有一個問題是ABA問題,解決方法是:加一個版本號。
- 詳情參考:
CAS
UnSafe類
- 內部有很多native方法,是執行的是C++的代碼,給了Java操作內存的方式
- 獲取Unsafe需要通過
反射
Unsafe類的屬性 - 常用的功能:CAS、加載類(可以不運行構造方法)、能直接操作內存、內置鎖的實現
- 詳情參考:
UnSafe類
AtomicInteger和AtomicBoolean:
- 是保證原子性的對象。
- 利用的CAS
- 詳情參考:
AtomicInteger
和AtomicBoolean
AtomicReference
- 是一個利用CAS幫助對象保證原子性的
- 但是存在ABA問題,解決該問題的是:AtomicStampedReference,詳情參考:
CAS
- 詳情參考:
AtomicReference
JUC工具包
CountDownLatch
- 通過一個計數器實現,計數器初始值就是線程的數量
- 每當一個線程完成任務,就會使計數減一
- 可以在多線程環境使用,使多個線程阻塞,等待上一階段任務的全部完成
- 詳情見:
CountDownLatch
CyclicBarrier
- 跟
CountDownLatch
的區別是:完成任務後需要等待其他線程完成任務,同時是一個可重用點 - 詳情見:
CyclicBarrier
Phaser
- JDK1.7之後引用的,具有
CyclicBarrier
和CountDownLatch
- 同時它的註冊數是支持動態增加或減少(可以用於線程出現異常)
- 當它在一個階段所有任務完成時,會進入下一階段,同時計數器重新恢復
- 詳情見:
Phaser
Exchanger
- 用於線程間交換數據
- 需要注意一點:交換的數據對象是一個引用,而不是拷貝,需要考慮線程安全問題
- 詳情見:
Exchanger
Semaphore
- 是一個對共享資源管理的設施,通過對信號量的控制,可以讓資源被多個線程訪問
- 詳情見:
Semaphore
ReentrantLock
- 支持公平鎖,即儘可能的保證線程之間獲取時間片的次數的相同的
- 支持tryLock機制,嘗試獲取鎖,如果沒有獲取到,不會阻塞
- 需要手動的釋放鎖,try…finally…
- 相較內置鎖而言,是基於AQS實現的,不需要一個從用戶態到內核態的過程,性能更高
- 是一個Java類,具有更多的功能,同時可以自由的擴展
- 詳情請見:
ReentrantLock
讀寫鎖
- 將讀和寫分爲兩個鎖,可以有效解決讀-讀之間的衝突問題,大幅提高性能
- 是悲觀鎖,可能讀的線程太多,寫的線程遲遲難以執行
- 詳情請見:
讀寫鎖
StampedLock
- 解決讀寫鎖中,寫的線程遲遲難以執行的過程,是一個樂觀鎖
- 思路是:獲得一個樂觀的讀鎖,先讀取數據;在返回數據時,檢測數據是否有被寫入,如果有,則獲取一個悲觀讀鎖,重新讀取數據
- 詳情請見:
StampedLock
三種鎖的比較
synchronized | StampedLock | Lock |
---|---|---|
是JVM的的內置鎖,每個JDK版本都會優化 | 是一個Java類,可以更好的擴展 | 是一個Java類,可以更好的擴展 |
都是悲觀鎖 | 提供了寫的樂觀鎖 | 都是悲觀鎖,但是提供了自旋鎖,或者不阻塞的獲取鎖 |
性能一般,因爲有一個從用戶態到內核態的過程 | 性能最好,可以代替讀寫鎖 | 性能十分不穩定,在複雜的讀寫環境下,性能十分差 |
- 詳情請見:
三種鎖的比較
ForkJoin
- 基本思想是:如果當前線程執行任務速度比較慢,則將此任務拆分,交給子線程執行
- 分爲Fork和Join兩個階段,充分利用CPU資源
- 詳情請見:
ForkJoin
Exectors框架
首先需要學習線程池的構造方法中參數的意義,如果可以儘量不要使用工廠方法創建線程池。
ThreadPoolExecutor
- 創建線程池有七大參數,
特別重要
- 有四種拒絕策略
- 四種阻塞隊列
- 一些調試的API
- 關閉線程池的注意事項
- 詳情請見:
ThreadPoolExecutor
Executors
用來創建線程池,可以創建5種線程池,需要對這些線程池特性很熟悉:
- newCachedThreadPool
- newFixedThreadPool
- newScheduledThreadPool
- newSingleThreadExecutor
- newWorkStealingPool
- 詳情請見:
Executors
CompletionService
- 用來增強線程池,主要思想是:
執行一批任務,先執行的,先獲取結果
- 實現的子類是:
ExecutorCompletionService
- 詳情請見:
CompletionService
CompleableFuture
- 可以進行串聯的操作,即利用上一個任務的結果,執行下一個任務
- 進行並聯的操作,即多個線程執行不同任務,最先執行完成的任務結果將作爲這一批任務的結果
- 可以不需要調用者主動獲取結果,而進行回調
- 執行一批任務時,獲取的Future是按照任務完成的順序
- 創建CompleableFuture有多種方式,最多的是
runAsync
和supplyAsync
- API分爲組合方法、中轉方法和終結方法
- 詳情請見:
CompleableFuture
文章名稱 | 鏈接 |
---|---|
ThreadPoolExecutor | https://blog.csdn.net/qq_43040688/article/details/106041236 |
Executors | https://blog.csdn.net/qq_43040688/article/details/106046629 |
CompletionService | https://blog.csdn.net/qq_43040688/article/details/106058225 |
CompleableFuture | https://blog.csdn.net/qq_43040688/article/details/106061776 |