1. 程式人生 > 程式設計 >java開發面試問答----多執行緒篇

java開發面試問答----多執行緒篇

建立多執行緒的方式

1)繼承Thread類建立執行緒

2)實現Runnable介面建立執行緒

3)使用Callable和Future建立執行緒

4)使用執行緒池

start()和run()的區別

run()是執行緒物件執行的內容,start()是啟動執行緒物件

如何建立一個執行緒池Excutorservice

  • 核心執行緒數
    • 當池中執行緒數小於核心執行緒數時建立新執行緒
    • 核心執行緒數不會被回收
  • 最大執行緒數
    • 當池中執行緒數大於核心執行緒數小於最大執行緒數且佇列滿時建立新執行緒
    • 大於核心執行緒數小於最大執行緒數的執行緒在空閒時間超過超時時間後會被回收
  • 阻塞佇列
    • 當池中執行緒數大於等於核心執行緒數時任務會優先放入佇列中
  • 常用的4種執行緒池
    • fixedThreadPool: 核心執行緒數和最大執行緒數定長,多的任務放入阻塞佇列中
    • cachedThreadPool: 核心執行緒數為0,最大執行緒數無限大,執行緒超過空閒時間時回收
    • scheduledThreadPool: 核心執行緒數定長,最大執行緒數無限大,執行緒執行完任務即回收,可週期性執行
    • singleThreadPool: 單執行緒,任務放入阻塞佇列中,用於順序執行

多執行緒同步有哪幾種方法

  • synchronized
  • lock
  • CountDownLatch

區別

  • synchronized是jvm層面的,而lock是第三方的類,都是可重入鎖
  • lock可以判斷鎖的狀態,trylock可以設定超時,lockInterruptibly可以中斷等待

synchronized鎖程式碼塊和鎖方法有什麼區別

  • 修飾方法
    • 修飾一般方法,鎖住的是物件,不同的物件是不同的鎖
    • 修飾靜態方法,鎖住的是類,該類的所有物件共享這把鎖
    • 物件被鎖時可以呼叫該物件的非同步方法
  • 修飾程式碼塊
    • 作用範圍是括號中的範圍
    • this: 鎖住的是物件
    • *.class: 鎖住的是類

鎖有哪些狀態(sleep和wait有什麼區別)

  • 鎖的狀態
    • 準備狀態
    • 就緒狀態
    • 執行狀態
    • 阻塞狀態
      • wait: object類,當前執行緒釋放了物件monitor變成掛起狀態,可用notify喚醒去搶奪物件monitor,多個執行緒等待時,notify只能隨機喚醒一個,全喚醒需要使用notifyAll
      • sleep: Thread類中,沒有釋放物件monitor,當前執行緒睡眠狀態,時間到後自動喚醒
    • 死亡狀態
  • ReentrantLock
    • lock的具體實現,是可重入鎖(同一個物件可重複遞迴呼叫的鎖)
    • 公平鎖是執行緒獲取鎖的順序是按照加鎖順序,非公平鎖則是搶鎖機制

什麼是樂觀鎖,什麼是悲觀鎖

  • 悲觀鎖:總是假設最壞的情況,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,如synchronized
  • 樂觀鎖:每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。如atomic包下面的原子變數,使用了volatile原語,實現方式是CAS:
    • V(需讀寫的記憶體位置)+A(準備用來比較的引數)+B(準備寫入的新值),若A的引數與V的對應的值相匹配,就寫入值B;若不匹配,就寫入這個不匹配的值而非B。

一致性hash演演算法

一致性hash採用的是環狀結構,hash出來的key落到順時針最近的結點上,這樣可以保證在結點增加刪除的情況下影響最小,而為了應對平衡性問題採用了虛擬結點的方式,將實際結點數放大,使key更均勻的落到每個結點上。

java執行緒池裡面的arrayblockingqueue,linkedblockingqueue的用途和區別

  • arrayblockingqueue是使用陣列實現的必須指定長度,為了達到環,當索引下標等於陣列長度時會歸0,put和take操作共用同一把鎖,資料的寫入和讀取只移動索引。
  • linkedblockingqueue是使用連結串列實現的,每次寫入會新增一個node放到連結串列尾部,讀取則從表頭刪除node,由於put和take單獨操作分別使用各自的鎖,在效率上比arrayblockingqueue要高。