Java並發知識點總結

來源:互聯網
上載者:User

標籤:任務   工作   結果   java記憶體模型   知識點   定義   執行   自己   對象   

 前言:Java語言一個重要的特點就是內建了對並發的支援,讓Java大受企業和程式員的歡迎。同時,如果想要提升自己的技術,Java並發知識必不可少,這裡簡單整理了一些相關內容,希望可以起到拋磚引玉的作用。

 

1,Java記憶體模型是什嗎?

        Java記憶體模型規定和指引Java程式在不同的記憶體架構、CPU和作業系統間有確定性地行為。它在多線程的情況下尤其重要。Java記憶體模型對一個線程所做的變動能被其它線程可見提供了保證,它們之間是先行發生關係。這個關係定義了一些規則讓程式員在並發編程時思路更清晰。比如,先行發生關係確保了:

        線程內的代碼能夠按先後順序執行,這被稱為程式次序規則。

        對於同一個鎖,一個解鎖操作一定要發生在時間上後發生的另一個鎖定操作之前,也叫做管程鎖定規則。

        前一個對volatile的寫操作在後一個volatile的讀操作之前,也叫volatile變數規則。

        一個線程內的任何操作必需在這個線程的start()調用之後,也叫作線程啟動規則。

        一個線程的所有操作都會線上程終止之前,線程終止規則。

        一個對象的終結操作必需在這個物件建構完成之後,也叫對象終結規則。

可傳遞性

更多介紹可以移步並發編程網:

(深入理解java記憶體模型系列文章:http://ifeve.com/java-memory-model-0)

 

2,Java中interrupted 和isInterruptedd方法的區別?

        interrupted() 和 isInterrupted()的主要區別是前者會將中斷狀態清除而後者不會。Java多線程的中斷機制是用內部標識來實現的,調用Thread.interrupt()來中斷一個線程就會設定中斷標識為true。當中斷線程調用靜態方法Thread.interrupted()來檢查中斷狀態時,中斷狀態會被清零。

        非靜態方法isInterrupted()用來查詢其它線程的中斷狀態且不會改變中斷狀態標識。簡單的說就是任何拋出InterruptedException異常的方法都會將中斷狀態清零。無論如何,一個線程的中斷狀態都有可能被其它線程調用中斷來改變。

 

3,Java中的同步集合與並發集合有什麼區別?

        同步集合與並發集合都為多線程和並發提供了合適的安全執行緒的集合,不過並發集合的可擴充性更高。在Java1.5之前程式員們只有同步集合來用且在多線程並發的時候會導致爭用,阻礙了系統的擴充性。Java5介紹了並發集合像ConcurrentHashMap,不僅提供安全執行緒還用鎖分離和內部分區等現代技術提高了可擴充性。

        不管是同步集合還是並發集合他們都支援安全執行緒,他們之間主要的區別體現在效能和可擴充性,還有他們如何?的安全執行緒上。

        同步HashMap, Hashtable, HashSet, Vector, ArrayList 相比他們並發的實現(ConcurrentHashMap, CopyOnWriteArrayList, CopyOnWriteHashSet)會慢得多。造成如此慢的主要原因是鎖, 同步集合會把整個Map或List鎖起來,而並發集合不會。並發集合實現安全執行緒是通過使用先進的和成熟的技術像鎖剝離。

        比如ConcurrentHashMap 會把整個Map 劃分成幾個片段,只對相關的幾個片段上鎖,同時允許多線程訪問其他未上鎖的片段。

        同樣的,CopyOnWriteArrayList 允許多個線程以非同步的方式讀,當有線程寫的時候它會將整個List複製一個副本給它。

        如果在讀多寫少這種對並發集合有利的條件下使用並發集合,這會比使用同步集合更具有延展性。

 

4,什麼是線程池? 為什麼要使用它?

        建立線程要花費昂貴的資源和時間,如果任務來了才建立線程那麼回應時間會變長,而且一個進程能建立的線程數有限。為了避免這些問題,在程式啟動的時候就建立若干線程來響應處理,它們被稱為線程池,裡面的線程叫背景工作執行緒。從JDK1.5開始,Java API提供了Executor架構讓你可以建立不同的線程池。比如單線程池,每次處理一個任務;數目固定的線程池或者是緩衝線程池(一個適合很多生存期短的任務的程式的可擴充線程池)

        線程池的作用,就是在調用線程的時候初始化一定數量的線程,有線程過來的時候,先檢測初始化的線程還有空的沒有,沒有就再看當前運行中的線程數是不是已經達到了最大數,如果沒有,就新分配一個線程去處理。

        就像餐館中吃飯一樣,從裡面叫一個服務員出來;但如果已經達到了最大數,就相當於服務員已經用盡了,那沒得辦法,另外的線程就只有等了,直到有新的“服務員”為止。

        線程池的優點就是可以管理線程,有一個高度中樞,這樣程式才不會亂,保證系統不會因為大量的並發而因為資源不足掛掉。

 

5,Java中活鎖和死結有什麼區別?

        活鎖:一個線程通常會有會響應其他線程的活動。如果其他線程也會響應另一個線程的活動,那麼就有可能發生活鎖。同死結一樣,發生活鎖的線程無法繼續執行。然而線程並沒有阻塞——他們在忙於響應對方無法恢複工作。這就相當於兩個在走廊相遇的人:甲向他自己的左邊靠想讓乙過去,而乙向他的右邊靠想讓甲過去。可見他們阻塞了對方。甲向他的右邊靠,而乙向他的左邊靠,他們還是阻塞了對方。

        死結:兩個或更多線程阻塞著等待其它處於死結狀態的線程所持有的鎖。死結通常發生在多個線程同時但以不同的順序請求同一組鎖的時候,死結會讓你的程式掛起無法完成任務。

 

6,如何避免死結?

死結的發生必須滿足以下四個條件:

        互斥條件:一個資源每次只能被一個進程使用。

        請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。

        不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。

        迴圈等待條件:若干進程之間形成一種頭尾相接的迴圈等待資源關係。

三種用於避免死結的技術:

        加鎖順序(線程按照一定的順序加鎖)

        加鎖時限(線程嘗試擷取鎖的時候加上一定的時限,超過時限則放棄對該鎖的請求,並釋放自己佔有的鎖)

        死結檢測

(死結原因及如何避免更深理解移步:http://blog.csdn.net/ls5718/article/details/51896159)

 

7,notify()和notifyAll()有什麼區別?
        1,notify()和notifyAll()都是Object對象用於通知處在等待該對象的線程的方法。
        2,void notify(): 喚醒一個正在等待該對象的線程。
        3,void notifyAll(): 喚醒所有正在等待該對象的線程。
兩者的最大區別在於:
         notifyAll使所有原來在該對象上等待被notify的線程統統退出wait的狀態,變成等待該對象上的鎖,一旦該對象被解鎖,他們就會去競爭。

         notify他只是選擇一個wait狀態線程進行通知,並使它獲得該對象上的鎖,但不驚動其他同樣在等待被該對象notify的線程們,當第一個線程運行完畢以後釋放對象上的鎖,此時如果該對象沒有再次使用notify語句,即便該對象已經空閑,其他wait狀態等待的線程由於沒有得到該對象的通知,繼續處在wait狀態,直到這個對象發出一個notify或notifyAll,它們等待的是被notify或notifyAll,而不是鎖。

 

8,什麼是可重新進入鎖(ReentrantLock)? 

        Java.util.concurrent.lock 中的 Lock 架構是鎖定的一個抽象,它允許把鎖定的實現作為Java 類,而不是作為語言的特性來實現。這就為Lock 的多種實現留下了空間,各種實現可能有不同的調度演算法、效能特性或者鎖定語義。            ReentrantLock 類實現了Lock ,它擁有與synchronized 相同的並發性和記憶體語義,但是添加了類似鎖投票、定時鎖等候和可中斷鎖等候的一些特性。此外,它還提供了在激烈爭用情況下更佳的效能。(換句話說,當許多線程都想訪問共用資源時,JVM可以花更少的時候來調度線程,把更多時間用在執行線程上。)
          Reentrant 鎖意味著什麼呢?簡單來說,它有一個與鎖相關的擷取計數器,如果擁有鎖的某個線程再次得到鎖,那麼擷取計數器就加1,然後鎖需要被釋放兩次才能獲得真正釋放。這模仿了synchronized 的語義;如果線程進入由線程已經擁有的監控器保護的synchronized 塊,就允許線程繼續進行,當線程退出第二個(或者後續)synchronized塊的時候,不釋放鎖,只有線程退出它進入的監控器保護的第一個synchronized 塊時,才釋放鎖。

 

9,讀寫鎖可以用於什麼應用情境?
        讀寫鎖可以用於 “多讀少寫” 的情境,讀寫鎖支援多個讀操作並發執行,寫操作只能由一個線程來操作
        ReadWriteLock對向資料結構相對不頻繁地寫入,但是有多個任務要經常讀取這個資料結構的這類情況進行了最佳化。ReadWriteLock使得你可以同時有多個讀取者,只要它們都不試圖寫入即可。如果寫鎖已經被其他任務持有,那麼任何讀取者都不能訪問,直至這個寫鎖被釋放為止。
ReadWriteLock 對程式效能的提高主要受制於如下幾個因素:
1,資料被讀取的頻率與被修改的頻率相比較的結果。
2,讀取和寫入的時間
3,有多少線程競爭

4,是否在多處理機器上運行

轉自http://www.cnblogs.com/peke/p/7912907.html

Java並發知識點總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.