當前位置:首頁 » 編程語言 » javaaqs

javaaqs

發布時間: 2023-05-24 10:48:52

java學會那些知識找工作才不費力

很多Java初學者會關心這么一個問題——Java學到什麼程度就可以出去找工作了?大家的目標都很明確,也很實在,學習Java無非就是為了找個工作,使自己和家人生活更好。那到底要學到那些Java知識,就可以去找第一份工作了呢?

下面咱們就以公司大小運用到的技術來解答,為什麼這樣說呢,小型的公司肯定沒有大型公司運用到的知識多,從另一個角度來看,大家也可以來測試一下自我學到的知識符合去一個什麼樣的企業。下面是我給大家總結和介紹。

1、中小型公司:

這類公司可以說特別的多,招聘和培訓可派歲瞎能會有自塵空己的一套標准,比如學歷上可能稍微做一些要求,技術上的把關也會有一定的方法,除了Java基礎知識和項目經歷之外,可能還會考查你的debug能力,代碼規范、異常處理能力,以及對一些Java高級特性的理解能力,可能最好多用過一些框架。

總而言之,這類公司選人的標准已經擁有了自我體系,不會像一些特別小的公司,招人很隨意,領導拍個板就行。當然,這類公司也吸引不到太多優秀人的人才,但是也確實可能會有一些踏實能乾的勤奮員工。

2、大中型公司:

這類公司一般都會要求本科學歷,對Java基礎知識要比較熟悉,最好能夠看過源碼,如果沒看過,那麼源碼方面的面試題好歹也要准備一下,除此之外,一般來說還會考察你的後端技術知識,比如資料庫、網路、操作系統,考察的不會太難,能把面經上的知識點掌握了就算是比較扎實了。

這類公司一般不會考太復雜的題目,更希望招一些水平能力都是中等的人才,只要知識面能比較廣,題目都能說到點子上,不需要掌握得特別深入,也可以有機會拿到offer。

其實歸結原因,就是因為二三線互聯網不太可能和一線公司爭奪一線人才,所以一般爭取的都是二線人才,不需要太優秀,但是至少要是中等水平,所以這些公司對很多程序員來說還是比較有機會的。

3、特大型公司:

要進這些公司,不僅要做到之前那些事情:掌握Java基礎、計算機基礎知識,並且是非常熟練地掌握,你需要深入理解每一個知識點,因為面試官會不斷深入地向你提問,了解你的知識深度,同時,你需要對源碼有所理解,在讀懂源碼的基礎上去理解框架的實現、JDK的實現。

另外,你需要對JVM有一個清晰的認識,不僅要了解其結構,垃圾回收原理,甚至還要知道如何在遇到線上問題時通過JVM調優來解決它們。

同理,你還需要對Java並發編程和網路編程的使用方法與底層實現原理非常熟悉,不僅僅答出NIO和BIO的區別,或者是synchronized和lock的區別,你還需要知道NIO的底層實現epoll是什麼,synchronized對應的mutexlock是什麼,lock和condition的實現原理又是什麼,而lock本身也是通過AQS、CAS操作類等組件來實現的,其中的內容實在太多,絕不只是幾道面試題就可以搞定的。

當然,除此之外,這些公司對資料庫、緩存、分布式技術等方面的要求都會比其他公司要高得多,你最好要搞懂MySQL的存儲引擎、索引和鎖的實現原理,Redis緩存的數據結構、備份方式、底層實現。同時如果你能理解負載均衡演算法、CAP理論,甚至是raft和paxos演算法,以及分布式常用技術如消息隊列、zookeeper等等,那麼無疑也是可以為你加分的技能。

為什麼大公司的要求這么高,因為它們是最好的互聯網公司,要招的自然也是最優秀的人才,如果考察底層原理還不能滿足他們篩選人才的需要,他們也會考察面試者的演算法能力,比如LeetCode上medium難度的原題,或者是劍指offer的變式題等等,演算法題相對考察理論基礎而言,篩選度更雀拆高,可以淘汰的人也更多。

② 並發編程解惑之線程

主要內容:

進程是資源分配的最小單位,每個進程都有獨立的代碼和數據空間,一個進程包含 1 到 n 個線程。線程是 CPU 調度的最小單位,每個線程有獨立的運行棧和程序計數器,線程切換開銷小。

Java 程序總是從主類的 main 方法開始執行,main 方法就是 Java 程序默認的主線程,而在 main 方法中再創建的線程就是其他線程。在 Java 中,每次程序啟動至少啟動 2 個線程。一個是 main 線程,一個是垃圾收集線程。每次使用 Java 命令啟動一個 Java 程序,就相當於啟動一個 JVM 實例,而每個 JVM 實例就是在操作系統中啟動的一個進程。

多線程可以通過繼承或實現介面的方式創建。

Thread 類是 JDK 中定義的用於控制線程對象的類,該類中封裝了線程執行體 run() 方法。需要強調的一點是,線程執行先後與創建順序無關。

通過 Runnable 方式創建線程相比通過繼承 Thread 類創建線程的優勢是避免了單繼承的局限性。若一個 boy 類繼承了 person 類,boy 類就無法通過繼承 Thread 類的方式來實現多線程。

使用 Runnable 介面創建線程的過程:先是創建對象實例 MyRunnable,然後將對象 My Runnable 作為 Thread 構造方法的入參,來構造出線程。對於 new Thread(Runnable target) 創建的使用同一入參目標對象的線程,可以共享該入參目標對象 MyRunnable 的成員變數和方法,但 run() 方法中的局部變數相互獨立,互不幹擾。

上面代碼是 new 了三個不同的 My Runnable 對象,如果只想使用同一個對象,可以只 new 一個 MyRunnable 對象給三個 new Thread 使用。

實現 Runnable 介面比繼承 Thread 類所具有的優勢:

線程有新建、可運行、阻塞、等待、定時等待、死亡 6 種狀態。一個具有生命的線程,總是處於這 6 種狀態之一。 每個線程可以獨立於其他線程運行,也可和其他線程協同運行。線程被創建後,調用 start() 方法啟動線程,該線程便從新建態進入就緒狀態。

NEW 狀態(新建狀態) 實例化一個線程之後,並且這個線程沒有開始執行,這個時候的狀態就是 NEW 狀態:

RUNNABLE 狀態(就緒狀敬春則態):

阻塞狀態有 3 種:

如果一個線程調用了一個對象的 wait 方法, 那麼這個線程就會處於等待狀態(waiting 狀態)直到另外一個線程調用這個對象的 notify 或者 notifyAll 方法後才會解除這個狀態。

run() 里的代碼執行完畢後,線程進入終結狀態(TERMINATED 狀態)。

線程狀態有 6 種:新建、可運行、阻塞、等待、定時等待、死亡。

我們看下 join 方法的使用:

運行結果:

我們來看下 yield 方法的使用:

運行結果:

線程與線程之間是無法直接通信的,A 線程無法直接通知 B 線程,Java 中線程之間交換信息是通過共享的內存來實現的,控制共享資源的讀寫的訪問,使得多個線程輪流執行對共享數據的操作,線程之間通信是通過對共享資源上鎖或釋放鎖來實現的。線程排隊輪流執行共享資源,這稱為線程的同步。

Java 提供了很多同森歷步操作(也就是線程間的通信方式),同步可使用 synchronized 關鍵字、Object 類的 wait/notifyAll 方法、ReentrantLock 鎖、無鎖同步 CAS 等方式來實現。

ReentrantLock 是 JDK 內置的一個鎖對象,用於線程同步(線程通信),需要用戶手動釋放鎖。

運行結果:

這表明同一時間段只能有 1 個線程執行 work 方法,因為 work 方法里的代碼需要獲取到鎖才能執行,這就實現了多個線程間的通信,線程 0 獲取鎖,先執行,線程 1 等待,線程 0 釋放鎖,線程 1 繼續執行。

synchronized 是一亮棚種語法級別的同步方式,稱為內置鎖。該鎖會在代碼執行完畢後由 JVM 釋放。

輸出結果跟 ReentrantLock 一樣。

Java 中的 Object 類默認是所有類的父類,該類擁有 wait、 notify、notifyAll 方法,其他對象會自動繼承 Object 類,可調用 Object 類的這些方法實現線程間的通信。

除了可以通過鎖的方式來實現通信,還可通過無鎖的方式來實現,無鎖同 CAS(Compare-and-Swap,比較和交換)的實現,需要有 3 個操作數:內存地址 V,舊的預期值 A,即將要更新的目標值 B,當且僅當內存地址 V 的值與預期值 A 相等時,將內存地址 V 的值修改為目標值 B,否則就什麼都不做。

我們通過計算器的案例來演示無鎖同步 CAS 的實現方式,非線程安全的計數方式如下:

線程安全的計數方式如下:

運行結果:

線程安全累加的結果才是正確的,非線程安全會出現少計算值的情況。JDK 1.5 開始,並發包里提供了原子操作的類,AtomicBoolean 用原子方式更新的 boolean 值,AtomicInteger 用原子方式更新 int 值,AtomicLong 用原子方式更新 long 值。 AtomicInteger 和 AtomicLong 還提供了用原子方式將當前值自增 1 或自減 1 的方法,在多線程程序中,諸如 ++i 或 i++ 等運算不具有原子性,是不安全的線程操作之一。 通常我們使用 synchronized 將該操作變成一個原子操作,但 JVM 為此種操作提供了原子操作的同步類 Atomic,使用 AtomicInteger 做自增運算的性能是 ReentantLock 的好幾倍。

上面我們都是使用底層的方式實現線程間的通信的,但在實際的開發中,我們應該盡量遠離底層結構,使用封裝好的 API,例如 J.U.C 包(java.util.concurrent,又稱並發包)下的工具類 CountDownLath、CyclicBarrier、Semaphore,來實現線程通信,協調線程執行。

CountDownLatch 能夠實現線程之間的等待,CountDownLatch 用於某一個線程等待若干個其他線程執行完任務之後,它才開始執行。

CountDownLatch 類只提供了一個構造器:

CountDownLatch 類中常用的 3 個方法:

運行結果:

CyclicBarrier 字面意思循環柵欄,通過它可以讓一組線程等待至某個狀態之後再全部同時執行。當所有等待線程都被釋放以後,CyclicBarrier 可以被重復使用,所以有循環之意。

相比 CountDownLatch,CyclicBarrier 可以被循環使用,而且如果遇到線程中斷等情況時,可以利用 reset() 方法,重置計數器,CyclicBarrier 會比 CountDownLatch 更加靈活。

CyclicBarrier 提供 2 個構造器:

上面的方法中,參數 parties 指讓多少個線程或者任務等待至 barrier 狀態;參數 barrierAction 為當這些線程都達到 barrier 狀態時會執行的內容。

CyclicBarrier 中最重要的方法 await 方法,它有 2 個重載版本。下面方法用來掛起當前線程,直至所有線程都到達 barrier 狀態再同時執行後續任務。

而下面的方法則是讓這些線程等待至一定的時間,如果還有線程沒有到達 barrier 狀態就直接讓到達 barrier 的線程執行任務。

運行結果:

CyclicBarrier 用於一組線程互相等待至某個狀態,然後這一組線程再同時執行,CountDownLatch 是不能重用的,而 CyclicBarrier 可以重用。

Semaphore 類是一個計數信號量,它可以設定一個閾值,多個線程競爭獲取許可信號,執行完任務後歸還,超過閾值後,線程申請許可信號時將會被阻塞。Semaphore 可以用來 構建對象池,資源池,比如資料庫連接池。

假如在伺服器上運行著若干個客戶端請求的線程。這些線程需要連接到同一資料庫,但任一時刻只能獲得一定數目的資料庫連接。要怎樣才能夠有效地將這些固定數目的資料庫連接分配給大量的線程呢?

給方法加同步鎖,保證同一時刻只能有一個線程去調用此方法,其他所有線程排隊等待,但若有 10 個資料庫連接,也只有一個能被使用,效率太低。另外一種方法,使用信號量,讓信號量許可與資料庫可用連接數為相同數量,10 個資料庫連接都能被使用,大大提高性能。

上面三個工具類是 J.U.C 包的核心類,J.U.C 包的全景圖就比較復雜了:

J.U.C 包(java.util.concurrent)中的高層類(Lock、同步器、阻塞隊列、Executor、並發容器)依賴基礎類(AQS、非阻塞數據結構、原子變數類),而基礎類是通過 CAS 和 volatile 來實現的。我們盡量使用頂層的類,避免使用基礎類 CAS 和 volatile 來協調線程的執行。J.U.C 包其他的內容,在其他的篇章會有相應的講解。

Future 是一種非同步執行的設計模式,類似 ajax 非同步請求,不需要同步等待返回結果,可繼續執行代碼。使 Runnable(無返回值不支持上報異常)或 Callable(有返回值支持上報異常)均可開啟線程執行任務。但是如果需要非同步獲取線程的返回結果,就需要通過 Future 來實現了。

Future 是位於 java.util.concurrent 包下的一個介面,Future 介面封裝了取消任務,獲取任務結果的方法。

在 Java 中,一般是通過繼承 Thread 類或者實現 Runnable 介面來創建多線程, Runnable 介面不能返回結果,JDK 1.5 之後,Java 提供了 Callable 介面來封裝子任務,Callable 介面可以獲取返回結果。我們使用線程池提交 Callable 介面任務,將返回 Future 介面添加進 ArrayList 數組,最後遍歷 FutureList,實現非同步獲取返回值。

運行結果:

上面就是非同步線程執行的調用過程,實際開發中用得更多的是使用現成的非同步框架來實現非同步編程,如 RxJava,有興趣的可以繼續去了解,通常非同步框架都是結合遠程 HTTP 調用 Retrofit 框架來使用的,兩者結合起來用,可以避免調用遠程介面時,花費過多的時間在等待介面返回上。

線程封閉是通過本地線程 ThreadLocal 來實現的,ThreadLocal 是線程局部變數(local vari able),它為每個線程都提供一個變數值的副本,每個線程對該變數副本的修改相互不影響。

在 JVM 虛擬機中,堆內存用於存儲共享的數據(實例對象),也就是主內存。Thread Local .set()、ThreadLocal.get() 方法直接在本地內存(工作內存)中寫和讀共享變數的副本,而不需要同步數據,不用像 synchronized 那樣保證數據可見性,修改主內存數據後還要同步更新到工作內存。

Myabatis、hibernate 是通過 threadlocal 來存儲 session 的,每一個線程都維護著一個 session,對線程獨享的資源操作很方便,也避免了線程阻塞。

ThreadLocal 類位於 Thread 線程類內部,我們分析下它的源碼:

ThreadLocal 和 Synchonized 都用於解決多線程並發訪問的問題,訪問多線程共享的資源時,Synchronized 同步機制採用了以時間換空間的方式,提供一份變數讓多個線程排隊訪問,而 ThreadLocal 採用了以空間換時間的方式,提供每個線程一個變數,實現數據隔離。

ThreadLocal 可用於資料庫連接 Connection 對象的隔離,使得每個請求線程都可以復用連接而又相互不影響。

在 Java 裡面,存在強引用、弱引用、軟引用、虛引用。我們主要來了解下強引用和弱引用:

上面 a、b 對實例 A、B 都是強引用

而上面這種情況就不一樣了,即使 b 被置為 null,但是 c 仍然持有對 C 對象實例的引用,而間接的保持著對 b 的強引用,所以 GC 不會回收分配給 b 的空間,導致 b 無法回收也沒有被使用,造成了內存泄漏。這時可以通過 c = null; 來使得 c 被回收,但也可以通過弱引用來達到同樣目的:

從源碼中可以看出 Entry 里的 key 對 ThreadLocal 實例是弱引用:

Entry 里的 key 對 ThreadLocal 實例是弱引用,將 key 值置為 null,堆中的 ThreadLocal 實例是可以被垃圾收集器(GC)回收的。但是 value 卻存在一條從 Current Thread 過來的強引用鏈,只有當當前線程 Current Thread 銷毀時,value 才能被回收。在 threadLocal 被設為 null 以及線程結束之前,Entry 的鍵值對都不會被回收,出現內存泄漏。為了避免泄漏,在 ThreadLocalMap 中的 set/get Entry 方法里,會對 key 為 null 的情況進行判斷,如果為 null 的話,就會對 value 置為 null。也可以通過 ThreadLocal 的 remove 方法(類似加鎖和解鎖,最後 remove 一下,解鎖對象的引用)直接清除,釋放內存空間。

總結來說,利用 ThreadLocal 來訪問共享數據時,JVM 通過設置 ThreadLocalMap 的 Key 為弱引用,來避免內存泄露,同時通過調用 remove、get、set 方法的時候,回收弱引用(Key 為 null 的 Entry)。當使用 static ThreadLocal 的時候(如上面的 Spring 多數據源),static 變數在類未載入的時候,它就已經載入,當線程結束的時候,static 變數不一定會被回收,比起普通成員變數使用的時候才載入,static 的生命周期變長了,若沒有及時回收,容易產生內存泄漏。

使用線程池,可以重用存在的線程,減少對象創建、消亡的開銷,可控制最大並發線程數,避免資源競爭過度,還能實現線程定時執行、單線程執行、固定線程數執行等功能。

Java 把線程的調用封裝成了一個 Executor 介面,Executor 介面中定義了一個 execute 方法,用來提交線程的執行。Executor 介面的子介面是 ExecutorService,負責管理線程的執行。通過 Executors 類的靜態方法可以初始化

ExecutorService 線程池。Executors 類的靜態方法可創建不同類型的線程池:

但是,不建議使用 Executors 去創建線程池,而是通過 ThreadPoolExecutor 的方式,明確給出線程池的參數去創建,規避資源耗盡的風險。

如果使用 Executors 去創建線程池:

最佳的實踐是通過 ThreadPoolExecutor 手動地去創建線程池,選取合適的隊列存儲任務,並指定線程池線程大小。通過線程池實現類 ThreadPoolExecutor 可構造出線程池的,構造函數有下面幾個重要的參數:

參數 1:corePoolSize

線程池核心線程數。

參數 2:workQueue

阻塞隊列,用於保存執行任務的線程,有 4 種阻塞隊列可選:

參數 3:maximunPoolSize

線程池最大線程數。如果阻塞隊列滿了(有界的阻塞隊列),來了一個新的任務,若線程池當前線程數小於最大線程數,則創建新的線程執行任務,否則交給飽和策略處理。如果是無界隊列就不存在這種情況,任務都在無界隊列里存儲著。

參數 4:RejectedExecutionHandler

拒絕策略,當隊列滿了,而且線程達到了最大線程數後,對新任務採取的處理策略。

有 4 種策略可選:

最後,還可以自定義處理策略。

參數 5:ThreadFactory

創建線程的工廠。

參數 6:keeyAliveTime

線程沒有任務執行時最多保持多久時間終止。當線程池中的線程數大於 corePoolSize 時,線程池中所有線程中的某一個線程的空閑時間若達到 keepAliveTime,則會終止,直到線程池中的線程數不超過 corePoolSize。但如果調用了 allowCoreThread TimeOut(boolean value) 方法,線程池中的線程數就算不超過 corePoolSize,keepAlive Time 參數也會起作用,直到線程池中的線程數量變為 0。

參數 7:TimeUnit

配合第 6 個參數使用,表示存活時間的時間單位最佳的實踐是通過 ThreadPoolExecutor 手動地去創建線程池,選取合適的隊列存儲任務,並指定線程池線程大小。

運行結果:

線程池創建線程時,會將線程封裝成工作線程 Worker,Worker 在執行完任務後,還會不斷的去獲取隊列里的任務來執行。Worker 的加鎖解鎖機制是繼承 AQS 實現的。

我們來看下 Worker 線程的運行過程:

總結來說,如果當前運行的線程數小於 corePoolSize 線程數,則獲取全局鎖,然後創建新的線程來執行任務如果運行的線程數大於等於 corePoolSize 線程數,則將任務加入阻塞隊列 BlockingQueue 如果阻塞隊列已滿,無法將任務加入 BlockingQueue,則獲取全局所,再創建新的線程來執行任務

如果新創建線程後使得線程數超過了 maximumPoolSize 線程數,則調用 Rejected ExecutionHandler.rejectedExecution() 方法根據對應的拒絕策略處理任務。

CPU 密集型任務,線程執行任務佔用 CPU 時間會比較長,應該配置相對少的線程數,避免過度爭搶資源,可配置 N 個 CPU+1 個線程的線程池;但 IO 密集型任務則由於需要等待 IO 操作,線程經常處於等待狀態,應該配置相對多的線程如 2*N 個 CPU 個線程,A 線程阻塞後,B 線程能馬上執行,線程多競爭激烈,能飽和的執行任務。線程提交 SQL 後等待資料庫返回結果時間較長的情況,CPU 空閑會較多,線程數應設置大些,讓更多線程爭取 CPU 的調度。

③ Java AQS如何清除垃圾節點

根據清除演算法,整理演算法,復制演算法,分代演算法進行清除。
清除演算法為標記無用對象,然後進行清除回收,缺點為效率不高,無法清除垃圾碎片。
整理演算法是標記無用對象,讓所有存活的對象都向一端移動,然後直接清除掉端邊界以外的內存。
復制演算法是按照容量劃分二個慧喊大小相等的內存區域,當一塊用完的時候將活著的對象復制到另一塊上,然後再把已使用的內存空間一次清理掉。缺點是內存使用率不高,只有原來的一半。
分代演算法是根據對象存活周期的不同將內存劃分為幾塊,一般是新生代和前罩野老年代,新生代基本採用復制演算法,老年代採用標記整悶弊理演算法。

④ 什麼是重入鎖和AQS

什麼是重入鎖

java.util.concurrent.locks.ReentrantLock

ReenTrantLock獨有的能力:

1.      ReenTrantLock可以指定是公平鎖還是非公平鎖。而synchronized只能是非公平鎖。所謂的公平鎖就是先等待的線程先獲得鎖。

2.      ReenTrantLock提供了一個Condition(條件)類,用來實現分組喚醒需要喚醒的線程們,而不是像synchronized要麼隨機喚醒一個線程要麼喚醒全部線程。

3.      ReenTrantLock提供了一種能夠中斷等待鎖的線程的機制,通過lock.lockInterruptibly()來實現這個機制。

非重入鎖

當A方法獲取鎖去鎖住一段需要做原子性操作的B方法時,如果這段B方法又需要鎖去做原子性操作,那麼A方法就必定要與B方法出現死鎖。這種會出現問題的重入一把鎖的情況,叫不可重入鎖。

lock的過程:

   首先嘗試獲取資源,如果當前狀態為0,表示沒有線程佔有鎖,設置該線程為獨占模式,使用CAS設置狀態,否則如果當前線程和獨占線程是一個線程,修改狀態值,否則返回false。

  若獲取資源失敗,則通過addWaiter <-(aqs)方法創建一個節點並放在CLH隊列的尾部。head tail未初始化會創建虛擬節點同時指向

為什麼 AQS 需要一個虛擬 head 節點

每個節點都需要設置前置Node 的 waitStatus  狀態(這個狀態為是為了保證數據一致性),防止重復釋放操作。而第一個節點是沒有前置節點的塵行,所以需要創建一個虛擬節點。

  逐步去執行CLH隊列中的線程,當前線程會公平性的阻塞一直到獲取鎖為止,返回線程在等待的過程中還是否中斷過。

unlock的過程

一次unlock操作需要修改狀態位,然後喚醒節點。整個釋放操作也是使用unpark()來喚醒隊列最前面的節點。其實lock中比較重要的也就是lock和release,它們又和AQS聯系緊密,下面會單獨談談AQS的重要方法。

Condition的await和signal

wait和notify/notify VS await和signal

Condition能夠支持不響應中斷,而通過使用Object方式不支持;

Condition能夠支持多個等待隊列(new 多個Condition對象),而Object方式只能支持一個;

Condition能夠支持超時時間的設置,而Object不支持

對標Object的wait方法

void await() throws InterruptedException:當前線程進入等待狀態,如果其他線程調用condition的signal或者signalAll方法並且當前線程獲取Lock從await方法返回,如果在等待狀態中被中斷會拋出被中斷異常;

long awaitNanos(long nanosTimeout):當前線程進入等待狀態直到被通知,中斷或者超時;

boolean await(long time, TimeUnit unit)throws InterruptedException:同第二種,支持自定義時間單位

boolean awaitUntil(Date deadline) throws InterruptedException:當前線程進入等待狀態直到被通知,中斷或高兄孝者到了某個時間

對標Object的notify/notifyAll方法

void signal():喚醒一個等待在condition上的線程,將該線程從等待隊列中轉移到同步隊列中,如果在同步隊列中能夠競爭到Lock則可以從等待方法中返回。

void signalAll():戚稿與1的區別在於能夠喚醒所有等待在condition上的線程

如圖所示,ConditionObject是AQS的內部類,因此每個ConditionObject能夠訪問到AQS提供的方法,相當於每個Condition都擁有所屬同步器的引用。

調用condition.await方法的線程必須是已經獲得了lock,也就是當前線程是同步隊列中的頭結點。調用該方法後會使得當前線程所封裝的Node尾插入到等待隊列中。

如圖,線程awaitThread先通過lock.lock()方法獲取鎖成功後調用了condition.await方法進入等待隊列,而另一個線程signalThread通過lock.lock()方法獲取鎖成功後調用了condition.signal或者signalAll方法,使得線程awaitThread能夠有機會移入到同步隊列中,當其他線程釋放lock後使得線程awaitThread能夠有機會獲取lock,從而使得線程awaitThread能夠從await方法中退出執行後續操作。如果awaitThread獲取lock失敗會直接進入到同步隊列。

// 線程已被取消

    static final int CANCELLED =  1;

    // 當前線程的後繼線程需要被unpark(喚醒)

    // 一般發生情況是:當前線程的後繼線程處於阻塞狀態,而當前線程被release或cancel掉,因此需要喚醒當前線程的後繼線程。

    static final int SIGNAL    = -1;

    // 在Condition休眠狀態,在等待Condition喚醒

    static final int CONDITION = -2;

    // (共享鎖)其它線程獲取到「共享鎖」,對應的waitStatus的值

    static final int PROPAGATE = -3;

volatile int waitStatus;

---------------------

/**

    * 這個方法也就是lock()方法的關鍵方法。tryAcquire獲得資源,返回true,直接結束。若未獲取資源,新建一個節點插入隊尾,

*addWaiter用於添加節點,也就是把當前線程對應的節點插入CLH隊列的尾部。

    * @param arg the acquire argument.  This value is conveyed to

    *        {@link #tryAcquire} but is otherwise uninterpreted and

    *        can represent anything you like.

    */

    public final void acquire(int arg) {

        if (!tryAcquire(arg) &&//獲取資源立刻結束

            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//沒有被中斷過,也結束

            selfInterrupt();

    }

---------------------

protected final boolean tryAcquire(int acquires) {

            final Thread current = Thread.currentThread();

            int c = getState();

            if (c == 0) {

                if (!hasQueuedPredecessors() &&

                    compareAndSetState(0, acquires)) {

                    setExclusiveOwnerThread(current);

                    return true;

                }

            }

            else if (current == getExclusiveOwnerThread()) { //判斷是否持有鎖的是自己,重入

                int nextc = c + acquires;

                if (nextc < 0)

                    throw new Error("Maximum lock count exceeded");

                setState(nextc);

                return true;

            }

            return false;

        }

---------------------

  * 非公平鎖

    */

    static final class NonfairSync extends Sync {

        private static final long serialVersionUID = 7316153563782823691L;

        /**

        * Performs lock.  Try immediate barge, backing up to normal

        * acquire on failure.

        */

        final void lock() {

            if (compareAndSetState(0, 1))//CAS設置當前為0 的時候上鎖

                setExclusiveOwnerThread(Thread.currentThread());

            else

                acquire(1);//否則嘗試獲得鎖。

        }

        protected final boolean tryAcquire(int acquires) {

            return nonfairTryAcquire(acquires);

        }

    }

    /**

    * 公平鎖

    */

    static final class FairSync extends Sync {

        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {

            acquire(1);

        }

        /**

        *

        */

        protected final boolean tryAcquire(int acquires) {

            final Thread current = Thread.currentThread();

            int c = getState();

            if (c == 0) {

                if (!hasQueuedPredecessors() &&

                    compareAndSetState(0, acquires)) {//沒有前驅節點並且CAS設置成功

                    setExclusiveOwnerThread(current);//設置當前線程為獨占線程

                    return true;

                }

            }

            else if (current == getExclusiveOwnerThread()) {//這里和非公平鎖類似

                int nextc = c + acquires;

                if (nextc < 0)

                    throw new Error("Maximum lock count exceeded");

                setState(nextc);

                return true;

            }

            return false;

        }

    }

⑤ JAVA鎖有哪些種類,以及區別

常見的Java鎖有下面這些:

  • 公平鎖/非公平鎖

  • 可重入鎖

  • 獨享鎖/共享鎖

  • 互斥鎖/讀寫鎖

  • 樂觀鎖/悲觀鎖

  • 分段鎖

  • 偏向鎖/輕量級鎖/重量級鎖

  • 自旋鎖

  • 這些分類並不是全是指鎖的狀態,有的指鎖的特性,有的指鎖的設計,下面總結的內容是對每個鎖的名詞進行一定的解釋。

    公平鎖/非公平鎖

    公平鎖是指多個線程按照申請鎖的順序來獲取鎖。
    非公平鎖是指多個線程獲取鎖的順序並不是按照申請鎖的順序,有可能後申請的線程比先申請的線程優先獲取鎖。有可能,會造成優先順序反轉或者飢餓現象。
    對於JavaReentrantLock而言,通過構造函數指定該鎖是否是公平鎖,默認是非公平鎖。非公平鎖的優點在於吞吐量比公平鎖大。
    對於Synchronized而言,也是一種非公平鎖。由於其並不像ReentrantLock是通過AQS的來實現線程調度,所以並沒有任何辦法使其變成公平鎖。

    可重入鎖

    可重入鎖又名遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,在進入內層方法會自動獲取鎖。說的有點抽象,下面會有一個代碼的示例。
    對於JavaReentrantLock而言, 他的名字就可以看出是一個可重入鎖,其名字是Re entrant Lock重新進入鎖。
    對於Synchronized而言,也是一個可重入鎖。可重入鎖的一個好處是可一定程度避免死鎖。

  • synchronized void setA() throws Exception{

  • Thread.sleep(1000);

  • setB();

  • }synchronized void setB() throws Exception{

  • Thread.sleep(1000);

  • }

  • 上面的代碼就是一個可重入鎖的一個特點,如果不是可重入鎖的話,setB可能不會被當前線程執行,可能造成死鎖。

    獨享鎖/共享鎖

    獨享鎖是指該鎖一次只能被一個線程所持有。
    共享鎖是指該鎖可被多個線程所持有。

    對於JavaReentrantLock而言,其是獨享鎖。但是對於Lock的另一個實現類ReadWriteLock,其讀鎖是共享鎖,其寫鎖是獨享鎖。
    讀鎖的共享鎖可保證並發讀是非常高效的,讀寫,寫讀 ,寫寫的過程是互斥的。
    獨享鎖與共享鎖也是通過AQS來實現的,通過實現不同的方法,來實現獨享或者共享。
    對於Synchronized而言,當然是獨享鎖。

    互斥鎖/讀寫鎖

    上面講的獨享鎖/共享鎖就是一種廣義的說法,互斥鎖/讀寫鎖就是具體的實現。
    互斥鎖在Java中的具體實現就是ReentrantLock
    讀寫鎖在Java中的具體實現就是ReadWriteLock

    樂觀鎖/悲觀鎖

    樂觀鎖與悲觀鎖不是指具體的什麼類型的鎖,而是指看待並發同步的角度。
    悲觀鎖認為對於同一個數據的並發操作,一定是會發生修改的,哪怕沒有修改,也會認為修改。因此對於同一個數據的並發操作,悲觀鎖採取加鎖的形式。悲觀的認為,不加鎖的並發操作一定會出問題。
    樂觀鎖則認為對於同一個數據的並發操作,是不會發生修改的。在更新數據的時候,會採用嘗試更新,不斷重新的方式更新數據。樂觀的認為,不加鎖的並發操作是沒有事情的。

    從上面的描述我們可以看出,悲觀鎖適合寫操作非常多的場景,樂觀鎖適合讀操作非常多的場景,不加鎖會帶來大量的性能提升。
    悲觀鎖在Java中的使用,就是利用各種鎖。
    樂觀鎖在Java中的使用,是無鎖編程,常常採用的是CAS演算法,典型的例子就是原子類,通過CAS自旋實現原子操作的更新。

    分段鎖

    分段鎖其實是一種鎖的設計,並不是具體的一種鎖,對於ConcurrentHashMap而言,其並發的實現就是通過分段鎖的形式來實現高效的並發操作。
    我們以ConcurrentHashMap來說一下分段鎖的含義以及設計思想,ConcurrentHashMap中的分段鎖稱為Segment,它即類似於HashMap(JDK7與JDK8中HashMap的實現)的結構,即內部擁有一個Entry數組,數組中的每個元素又是一個鏈表;同時又是一個ReentrantLock(Segment繼承了ReentrantLock)。
    當需要put元素的時候,並不是對整個hashmap進行加鎖,而是先通過hashcode來知道他要放在那一個分段中,然後對這個分段進行加鎖,所以當多線程put的時候,只要不是放在一個分段中,就實現了真正的並行的插入。
    但是,在統計size的時候,可就是獲取hashmap全局信息的時候,就需要獲取所有的分段鎖才能統計。
    分段鎖的設計目的是細化鎖的粒度,當操作不需要更新整個數組的時候,就僅僅針對數組中的一項進行加鎖操作。

    偏向鎖/輕量級鎖/重量級鎖

    這三種鎖是指鎖的狀態,並且是針對Synchronized。在Java 5通過引入鎖升級的機制來實現高效Synchronized。這三種鎖的狀態是通過對象監視器在對象頭中的欄位來表明的。
    偏向鎖是指一段同步代碼一直被一個線程所訪問,那麼該線程會自動獲取鎖。降低獲取鎖的代價。

    輕量級鎖是指當鎖是偏向鎖的時候,被另一個線程所訪問,偏向鎖就會升級為輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,提高性能。
    重量級鎖是指當鎖為輕量級鎖的時候,另一個線程雖然是自旋,但自旋不會一直持續下去,當自旋一定次數的時候,還沒有獲取到鎖,就會進入阻塞,該鎖膨脹為重量級鎖。重量級鎖會讓其他申請的線程進入阻塞,性能降低。

    自旋鎖

    在Java中,自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是採用循環的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環會消耗CPU。

⑥ 有沒有關於java深入一點的書推薦

學習的最好途徑就是看書「,這是我自己學習並且小有了一定的積累之後的第一體會。個人認為看書有兩點好處:

1.能出版出來的書一定是經過反復的思考、雕琢和審核的,因此從專業性的角度來說,一本好書的價值遠超其他資料。

2.對著書上的代碼自己敲的時候方便。

「看完書之後再次提升自我的最好途徑是看一些相關的好博文「,我個人認為這是學習的第二步,因為一本書往往有好幾百頁,好的博文是自己看書學習之後的一些總結和提煉,對於梳理學習的游蠢扮內容很有好處,當然這里不是說自己的學習方法,就不再扯下去了。

很多程序員們往往有看書的沖動,但不知道看哪些書,下面我就給各位Java程序猿們推薦一些好書(每本書的作者會加粗標紅),其中絕大多數都是我自己平時在看的書,也算是我對於平時讀的書做一個小總結和讀後感吧。

首先推薦的不是一本書,而是一個博客,也是我們博客園另外一位博友java_my_life。

目前市面上講解設計模式的書很多,雖然我前面講了看書是最好的,但是對設計模式感興趣的朋友們,我推薦的是這個博客。這位博友的設計模式講得非常非常好,我認為90%的內容都是沒有問題且很值得學習的,其講解設計模式的大體路線是:

隨便開篇點明該設計模式的定義

圖文並茂講解該設計模式中的結構

以詳細的代碼形式寫一下該種設計模式的實現

補充內容

講解該設計模式的優缺點


對於一個設計模式我們關注、學習的知識點,不就是上面這些嗎?

不過我要重點提醒一下網友們,同一種設計檔衫模式的寫法有多種,並不是說只有按某種寫法來寫才是這種設計模式。比方說適配器模式,我們關注適配器模式一定要關注的是什麼是適配器模式不是怎麼寫適配器模式,不要認為某段代碼不是按照適配器模式的寫法寫下來的它就不是適配器模式了,記住這一點,你在學習設計模式的時候一定會對代碼中用到的設計模式有更深入的理解。


1、深入理解Java虛擬機:JVM高級特性與最佳實踐


如果你不滿足於做一個只會寫ifelse的Java程序員,而是希望更進一步,我隨便舉幾個例子吧:

了解Java代碼的底層運行機制

定位性能問題

對整個系統進行性能調優

解決各種奇奇怪怪的線上線下問題

更加高級別的,為自己的項目量身定做一款適合自己項目的虛擬機

那麼Java虛擬機是你必學的一門技術。《深入理解Java虛擬機:JVM高級特性與最佳實踐》作者是周志明,這本書可以說是國內寫得最好的有關Java虛擬機的書籍,近半年,前前後後這本書我起碼看了有5遍。國內寫虛擬機的書除了這本,其實還有一些其他的,我也買過,不過粗略看下來,很多內容也是《深入理解Java虛擬機:JVM高神灶級特性與最佳實踐》此書裡面的。

另外值得一提的是,《深入理解Java虛擬機:JVM高級特性與最佳實踐》這本書,有電子版的,網上搜一下就能下載到了。不過建議有興趣的朋友還是去買書看,電子版本下載到的一般是比較老的版本,相比最新修訂版的《深入理解Java虛擬機:JVM高級特性與最佳實踐》,有很多作者新補充的知識點是沒有的。


2、HotSpot實戰


所有的Java虛擬機都是遵循著Java虛擬機規范來的,市面上的Java虛擬機幾十款,《深入理解Java虛擬機:JVM高級特性與最佳實踐》一書裡面講的虛擬機並不針對某種特定的虛擬機,而是從Java虛擬機規范的角度來講解Java虛擬機。

我們平時使用的乃至商用的大多數Java虛擬機都是Sun公司的HotSpot,大家cmd進入命令行,使用」java-version」命令就可以看到了。如果希望在Java虛擬機規范的基礎上更加深入地去理解虛擬機的一些細節是怎麼實現的,就可以看一下《HotSpot實戰》一書,作者是陳濤。不過由於HotSpot的源碼都是C/C++寫的,所以要求讀者有非常好的C/C++基礎,如果對這兩門語言不是很熟悉的朋友,看這本書可能對你幫助不是很大。

最後提一句,如果有興趣的朋友,不妨先去網上下載一個openJDK,HotSpot的源碼就在裡面。


3、Java並發編程實戰



這本書常常被列入Java程序員必讀十大書籍排行榜前幾位,不過個人不是很推薦這本書。

《Java並發編程實戰》作者是BrianGoetz,怎麼說呢,這本書前前後後我也看了兩遍左右,個人感受是:

文字多代碼少

講解多實踐少

我覺得這可能就是老外寫書的特點吧,因為Java是北美國家(加拿大、美國)開發和維護的,所以老外對Java方方面面的理論知識體系都掌握得是非常清楚和透徹的。翻開這本書看,多線程什麼用、什麼是死鎖、什麼是競爭、什麼是線程安全等等,方方面面的知識點都用大量的文字篇幅講解,不免讓人感覺十分枯燥,也難讓讀者有實質性的進步。我這本書看了兩遍也屬於一目十行意思,有興趣的地方就重點看一下。

無論如何,作為一本常常位於Jva程序員必讀十大書籍排行榜前幾名的書,還是一定要推薦給大家的。

4、java多線程編程核心技術


《Java多線程編程核心技術》作者高洪岩。想要學習多線程的朋友,這本書是我大力推薦的,我的個人博客裡面二十多篇的多線程博文都是基於此書,並且在這本書的基礎上進行提煉和總結而寫出來的。

此書和《Java並發編程實戰》相反,這本書的特點是大篇幅的代碼+小篇幅的精講解,可能這和中國人寫的書比較偏向實用主義的風格有關。本書關於線程安全、synchronized、Reentrant、Timer等等都用詳細的代碼進行了講解,而且每個大知識點下的多個小知識點都會詳細講解到,非常有實踐價值。

有興趣的朋友們,我相信只要你們跟著這本書裡面的代碼敲、運行、思考,三步走,對於多線程的使用與理解一定會進幾大步。

不過這本書的缺點就是對於Java並發包下的一些類像CountDownLatch、Semphore、CyclicBarrier、Future、Callable等都沒有講到,重點的CAS和AQS也沒有觸及,重點類的實現原理也沒有提。當然,這很深入了,在學習了這本書之後如果能再去對這些知識進行一些學習、研究的話,你一定會慢慢成長為一個很厲害的多線程高手。


5、EffectiveJava中文版


這是唯一一本我沒有買的書。初識這本書,是在我的博文Java代碼優化(長期更新)裡面,底下評論的時候有朋友提到了這本書,當時我說要去買,不過這兩個月一直都沒時間去逛書店,甚是遺憾,之後肯定會找時間去買這本書的。

《EffectiveJava中文版》的作者是JoshuaBloch,這個人就很厲害了,他是谷歌的首席架構師,屬於超級技術大牛級別了吧,呵呵。由於沒有看過這本書,所以我不好發表評論,但是從這本書的知名度以及其作者的來頭來看(多提一句,這本書也是Java之父JamesGosling博士推崇的一本書),我相信這一定是一本值得一看的好書。

好的代碼是每個Java程序員都應該去追求的,不是說我今天寫一段好代碼相比寫一段爛代碼對性能會有多大的提升,更多的應該是提升了代碼的可讀性以及可以規避許多潛在的、未知的問題,避免代碼上線之後出問題而花時間去維護—-無論從時間成本、人力成本還是風險成本來說,這都是非常高的。


6、深入分析JavaWeb技術內幕


《深入分析JavaWeb技術內幕》,作者許令波,淘寶工程師。

這本書我用一個字概括就是:全。真的非常全,HTTP、DNS、CDN、靜態化、Jetty、Tomcat、Servlet、Spring、MyBatis等等,什麼都有,涉及知識面非常廣,但又不像專門精講某個知識點的書籍一樣講得非常深入,感覺這本書就是盡量去用短的篇幅講清楚一些JavaWeb使用到的技術的內幕,讓讀者對這些知識點的技術內幕有一個理性的認識。

不過,盡管每個知識點的篇幅都不多,但是重點都基本講到了,是一本讓人真正有收獲的書。如果想進一步了解這些技術的技術內幕,就要自己去買相關書籍或者自己上網查資料了,有種拋磚引玉,或者說師傅領進門、修行在個人的感覺。


7、大型網站技術架構核心原理與案例分析


一個字評價這本書,_;兩個字評價這本書,很_;三個字評價這本書,非常_。呵呵,好了,再說下去可能別人以為我是水軍了。

《大型網站技術架構核心原理與案例分析》的作者是李智慧,原阿里巴巴技術專家。

Java的大多數應用都是用在Web上的,現在只要稍微大型一點的Web應用,都一定是一個分布式系統,那麼一個分布式系統用到了哪些技術?一個大型網站是如何從一個小型網站成長起來的?如何保證你的網站安全?分布式系統使用到了緩存,有哪些緩存?緩存的使用有哪些值得注意的事項?

關於分布式的知識點,都在這本書裡面有體現,只有你想不到,沒有他寫不到,而且寫得非常易懂,基本屬於看一兩遍,再記一些筆記就知道是怎麼一回事兒了。多看幾遍,對分布式的理解一定會加深不少。而且裡面不僅僅是分布式的知識,還非常接地氣地寫了如何做一個好的架構師,其實我認為這不僅僅是寫給想做架構師的讀者看的,就是給讀者一些建議,如何更好地提出意見、如何更讓別人關注你的聲音、如何看到他人的優點,入木三分,讓人獲益匪淺。


8、大型網站系統與Java中間件實踐


《大型網站系統與Java中間件實踐》作者曾憲傑,是淘寶的技術總監,算起來應該在阿里有至少P8的級別了吧。

這本書的部分內容和上面一本李智慧的《大型網站技術架構核心原理與案例分析》有所重合,像分布式系統的演化、CDN、CAP理論和BASE理論等等,這也更說明這些都是分布式系統或者說是一個大型網站重點關注的內容,當作一次再學習也不錯。

本書要突出的重點是中間件三個字,中間件是分布式系統中一個非常重要的東西,其最重要的作用應該就是解耦,降低模塊與模塊之間的強依賴,不同的模塊之間的依賴度降低,便可以各自獨立地開發自己的功能,這也可以說是軟體工程發展的目標和驅動力。

因此,本書有一部分的內容就是基於中間件,詳細講解了中間件與JMS的各種知識,適合對分布式系統比較熟悉並且想要往中間件方面有一定研究的讀者。


9、從Paxos到ZooKeeper分布式一致性原理與實踐


《從Paxos到ZooKeeper分布式一致性原理與實踐》,作者倪超,阿里巴巴工程師。

這本書是我最近在研讀的一本書,和上面的《大型網站系統與Java中間件實踐》一樣,屬於分布式組件的范疇,屬於有些深入的內容,當然也是我自己的個人興趣。當然,如果有志向做一個出色的大型網站架構師、公司的技術總監之類,這些知識當然是必須掌握的。

本書從分布式系統基本理論開始講起,講到Paxos演算法,最後慢慢引入到Zookeeper,循序漸進。當然,更多的我目前還不方便發表什麼看法,因為這本書的第二張Paxos演算法我都還沒有弄懂(Paxos演算法確實有些難以理解和不太易懂),接下來的章節還沒有看下去。

如果網友們所在的公司在使用Zookeeper,並且你又對Zookeeper感興趣想要研究一下它的原理的,這本書將是不二之選。


10、MySQL5.6從零開始學


《MySQL5.6從零開始學》,作者劉增傑和李坤。

作為一名Java程序員,我認為我們千萬不要覺得資料庫是DBA的事情,資料庫對一個Java程序員來說也是必須掌握的一門知識,豐富的資料庫性能優化經驗是一個頂尖程序員必備技能。

目前主流的資料庫有Oracle和MySQL,當然推薦大家的是MySQL,主要原因我認為有兩點:

1、MySQL相比Oracle更輕量級、更小、安裝和卸載更方便,SQL其實都是差不多的,如果想學資料庫,學MySQL就可以了,在家裡面可以自己方便地研究,如果你的公司使用Oracle,只要再用對比學習法,關注一下Oracle和MySQL的差別即可

2、隨著2009年阿里巴巴去IOE的運動的進行,目前國內的很多互聯網公司都會選擇MySQL作為它們使用的資料庫,因為MySQL免費,所以既省錢又不需要出了問題就依賴甲骨文公司

MySQL學習我推薦的是這本我自己學習看的《MySQL5.6從零開始學》,我是覺得挺好的這本書,書裡面的知識點很細致、很全面,讀者選擇書籍的標准大多不就是這兩點嗎?


11、Spring源碼深度解析


《Spring源碼深度解析》,作者郝佳。

Spring這個框架做得太好了,功能太強大了,以至於很多開發者都只知Spring,不知什麼是工廠、什麼是單例、什麼是代理(我面試別人的真實體會)。這種功能強大的框架內部一定是很復雜的實現,這就導致一旦你的程序使用Spring,出了問題,可能是Error、可能是Exception、可能是程序運行結果不是你的預期的,出現諸如此類問題的時候,將會讓你感到困惑,除了上網查資料或者問別人似乎沒有更好的解決辦法。

研讀Spring的源代碼不失為一種很好的學習方法,我個人認為這有很多好處:

理解框架內部的實現之後,可以主動去解決問題,而不需要依賴別人

Spring框架內部實現用到了很多設計模式,很好的代碼設計思路,這將會對你寫代碼、對你理解設計模式有很大的提高

研究Spring框架將會大大增強你讀代碼的能力,我相信只要你能研究清楚Spring內部是如何實現的,其他任何一個框架的源代碼都難不倒你

總而言之,我認為讀代碼的能力是一個普通的程序員和一個好的程序員之間最大的差別之一,前者只會把別人寫好的東西拿來用,後者不僅能用好,還清楚知道別人寫好的東西底層是如何實現的,在出現問題的時候可以輕松解決。

Spring源代碼,個人推薦《Spring源碼深度解析》一書,真要研究透並且寫清楚Spring源代碼,恐怕三四本書都不夠,作者在近400頁的篇幅中盡量去講解Spring源代碼是如何實現的,殊為不易,盡管無法講得完全,但是相信作者的講解配合上讀者自己的研究,一定可以對Spring的實現有更深度的理解。


以上就是我對Java高級部分應該看的書籍的推薦,希望可以對你有所幫助。說一點我的建議,我們學Java技術更重要的還是看視頻教程,我們只有看更多的視頻教程,不斷的練習,在腦海當中產生深刻的記憶。我永遠堅信我的一句話:書籍能詮釋的東西畢竟有限。


最後在這里推薦大家關注一下我的微信公眾號:Java新手學習,給你准備了一套最新的Java基礎精講視頻教程和Java系統學習路線,關注即可觀看。


⑦ 實戰Java高並發程序設計讀後感10篇_讀後感_名著讀後感

《實戰Java高並發程序設計》是一本由葛一鳴 / 郭超著作,電子工業出版社出版的平裝圖書,本書定價:69.00元,頁數:352,文章吧我精心整理的一些讀者的讀後感,希望對大家能有幫助。

《實戰Java高並發程序設計》讀後感(一):是本入門書籍

這是一本Java並發基礎以及conCurrent包的類的簡介,雖然書名是實戰,但是例子挺多都是屬於helloWorld級別的,所以是比較適合入門。同時也會夾著一些對源碼和數據機構的分析,也會有Java8帶來一些新特性(比如函數式編程等)的講解,所以還可以吧。

還有一點就是這本書的圖會比較新穎和奇葩,例如下面這樣的:

有時候會覺得挺形象的,更多的時候是不想吐槽(有些字一下子還看不出來是什麼字o(╯□╰)o),還是希望用專業的畫圖軟體畫吧.

再去找一個並發的書籍看看加強~並發真的需要好好學學

《實戰Java高並發程序設計》讀後感(二):全面了解Java並發編程的好書

1.這本書的章節編排是比較清晰的,而且是由淺入深、由理論到實戰,閱讀的時候感覺特別流暢;

2.如果你翻過這本書,你一定會對書中的插圖印象「深刻」,很難想像現代出版的書里的插圖是這種質量;

3.關於Java並發的知識可以說是介紹得比較全面了,當前全面的話可能就沒法真正的深入,比如ConcurrentHashMap基本上並發編程中最常用最經典的設計,但是書上介紹的非常少;同樣的,Java 8中引入的CompletableFuture也是一個很重要的工具但是介咐頃紹的篇幅也非常有限;

4.對於Akka這一塊,說實話我讀了兩遍,還是沒有看得很懂,通過閱讀官方的文檔才比較清晰,感覺這一塊寫得有點混亂,條理不夠清晰;

5.最終我還是給這本書四星,因為讀後自己確實對並發這一塊有了比較完整的認識,讀後結合《深入理解Java虛擬機(第2版)》,從項目中的代碼找到並相關部分並予以改進,梳理並發重點的知識(顯式鎖控制、並發容器、並發流),收獲還是挺多的。

《實戰Java高並發程序設計》讀後感(三):Java並發編程和高並發解決方案視頻課程

Java並發編程和高並發解決方案視頻課程

網盤地址://pan./s/19tUBliZIYy2HQ0LiVfCw-A 密碼: d9fb

備用地址(騰訊微雲)://share.weiyun/5grRNnM 密碼:e324w9

學會高並發處理思路與手段,讓跳槽面試從容不迫,並發與高並發是面試的重要考察點,常問面試問題與答案都在這里了!

無論面試還是實際開發,幾乎都會涉及並發相關知識及高並發相關場景處理,如果你想系統的學習一下並發編程

並了解一下實際的高並發場景及應對方案,那這門課就是為你准備的。

第1章 課程准備衡好陸

第2章 並發基礎

第3章 項目准備

第4章 線程安全性

第5章 安全發布對象

第6章 線程安全策略

第7章 J.U.C之AQS

第8章 J.U.C組件拓展

第9章 線程調度-線程池

第10章 多線程並發拓展

第11章 高並發之擴容思路

第12章 高並發之緩存思路

第13章 高並發之消息隊列思路

第14章 高並發之應用拆分思路

第15章 高並發之應用限流思路

第16章 高並發之服務降級與服務熔斷思路

第17章 高並發之資料庫切庫分庫分表思路

第18章 高並發之高可用手段介紹

第19章 課程總結

《實戰Java高並發程序設計》讀後感(四):實戰Java高並發程序設計書評

說實話,在當當上找了很多有關java並發編程的書籍,最後也不知道是什麼原因買了這本書(好像是這本書有優惠。。。)買來之後看了,簡直後悔得不行!

這本書的作者是葛一鳴和郭超,出版社是電子工業出版社!

首先,這本書的作者的寫作態度值得懷疑,書中的配圖完全是手畫的,而且畫的質量實在不敢恭維,寫過的論文都應該知道,畫圖應該襪爛用Visio。實在納悶那麼多專業的圖,作者為何不用Visio或其他專業畫圖軟體,選擇用手畫是幾個意思,關鍵畫的質量還不咋地,歪七八糟的,看都看不清楚!作為一個專業的出版社,編輯也能審核通過,我是佩服出版社的編輯的審稿能力!

其次,關於java並發這塊,這本書連入門書籍都算不上,只能算是科普下,書中涉及到的並發知識,比如java內存模型,volatile,鎖等,作者都沒有深入原理的講,基本上都是簡單帶過,遠不如網路來的講得好,其中講volatile的一段:「和原子性問題一樣,我們只要簡單地使用volatile來聲明ready變數,告訴java虛擬機,這個變數可能會在不同的線程中修改,這樣就可以順利的解決這個問題了。」 不知道大家覺得怎麼樣,反正我看完想說臟話,作者你就是這么講解技術的嗎?用volatile來告訴虛擬機變數會在不同線程中修改??我只能說呵呵

還有一點,其他豆瓣網友也提到過,很多內容以及代碼都是從其他博客、文章過來,作者原創的有價值的東西,幾乎為零。

書中還有其他一些低級錯誤,就不一一指出了,最後,如果有幸能夠被作者看到此評論,真心希望作者好好反思下,請你為寫出的書負責,確保產出原創的有意義的內容,不是隨意幾段文字和代碼,整理下就能出書的,請你對得起買書的讀者!

熱點內容
如何設置強緩存的失效時間 發布:2025-05-19 15:21:28 瀏覽:695
winxp無法訪問 發布:2025-05-19 15:19:48 瀏覽:947
文件預編譯 發布:2025-05-19 15:14:04 瀏覽:643
怎麼在伺服器上掛公網 發布:2025-05-19 15:14:02 瀏覽:272
濟南平安e通如何找回密碼 發布:2025-05-19 14:56:58 瀏覽:176
安卓手機如何找到iccid碼 發布:2025-05-19 14:46:51 瀏覽:227
編譯的內核為什麼那麼大 發布:2025-05-19 14:45:21 瀏覽:179
什麼控制壓縮 發布:2025-05-19 14:28:13 瀏覽:931
網路伺服器忙指什麼 發布:2025-05-19 14:28:10 瀏覽:189
伺服器有外網ip 發布:2025-05-19 14:02:02 瀏覽:833