多線程常問面試題總結,理解後幫助進階高級Java工程師

多線程的價值?

  • 發揮多核CPU的優勢
  • 防止阻塞
  • 便於建模

線程和進程的區別?

一個程序下至少有一個進程,一個進程下至少有一個線程,一個進程下也可以有多個線程來增加程序的執行速度。

守護線程是什麼?

守護線程是運行在後臺的一種特殊進程。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。在 Java 中垃圾回收線程就是特殊的守護線程。

創建線程的有哪些方式?

  • 繼承Thread類創建線程類
  • 通過Runnable接口創建線程類
  • 通過Callable和Future創建線程
  • 通過線程池創建

Java線程具有五中基本狀態

1)新建狀態(New):當線程對象對創建後,即進入了新建狀態,如:Thread t = new MyThread();

2)就緒狀態(Runnable):當調用線程對象的start()方法(t.start();),線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了準備,隨時等待CPU調度執行,並不是說執行了t.start()此線程立即就會執行;

3)運行狀態(Running):當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。注:就緒狀態是進入到運行狀態的唯一入口,也就是說,線程要想進入運行狀態執行,首先必須處於就緒狀態中;

4)阻塞狀態(Blocked):處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU調用以進入到運行狀態。
根據阻塞產生的原因不同,阻塞狀態又可以分爲三種:
等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;
同步阻塞 – 線程在獲取synchronized同步鎖失敗(因爲鎖被其它線程所佔用),它會進入同步阻塞狀態;
其他阻塞 – 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

5)死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

什麼是線程池?

線程池就是提前創建若干個線程,如果有任務需要處理,線程池裏的線程就會處理任務,處理完之後線程並不會被銷燬,而是等待下一個任務。由於創建和銷燬線程都是消耗系統資源的,所以當你想要頻繁的創建和銷燬線程的時候就可以考慮使用線程池來提升系統的性能。

四種線程池的創建:

  • newCachedThreadPool創建一個可緩存線程池
  • newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數。
  • newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
  • newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務。

線程池的優點?

  • 重用存在的線程,減少對象創建銷燬的開銷。
  • 可有效的控制最大併發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
  • 提供定時執行、定期執行、單線程、併發數控制等功能。

多線程常用方法描述

方法名

作用

run()

需要執行的代碼

start()

啓動線程

sleep()

阻塞當前線程

yield()

與sleep()類似,只是不能由用戶指定暫停多長時間,並且yield()方法只能讓同優先級的線程有執行的機會。

wait()

釋放當前線程鎖

join()

加入一個線程,等待加入線程執行後在執行當前線程

Thread.CurrentThread()

獲取當前線程

 

sleep() 和 wait() 有什麼區別?

  • 類的不同:sleep() 來自 Thread,wait() 來自 Object。
  • 釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
  • 用法不同:sleep() 時間到會自動恢復;wait() 可以使用 notify()/notifyAll()直接喚醒。

notify()和 notifyAll()有什麼區別?

notifyAll()會喚醒所有的線程,notify()之後喚醒一個線程。notifyAll() 調用後,會將全部線程由等待池移到鎖池,然後參與鎖的競爭,競爭成功則繼續執行,如果不成功則留在鎖池等待鎖被釋放後再次參與競爭。而 notify()只會喚醒一個線程,具體喚醒哪一個線程由虛擬機控制。

線程的 run() 和 start() 有什麼區別?

start() 方法用於啓動線程,run() 方法用於執行線程的運行時代碼。run() 可以重複調用,而 start() 只能調用一次。

如何保證多線程的運行安全?

  • 使用安全類,比如 Java. util. concurrent 下的類。
  • 使用自動鎖 synchronized。
  • 使用手動鎖 Lock。

什麼是死鎖?

當線程 A 持有獨佔鎖a,並嘗試去獲取獨佔鎖 b 的同時,線程 B 持有獨佔鎖 b,並嘗試獲取獨佔鎖 a 的情況下,就會發生 AB 兩個線程由於互相持有對方需要的鎖,而發生的阻塞現象,我們稱爲死鎖。

怎麼防止死鎖?

  • 儘量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設置超時時間,超時可以退出防止死鎖。
  • 儘量使用 Java.util.concurrent 併發類代替自己手寫鎖。
  • 儘量降低鎖的使用粒度,儘量不要幾個功能用同一把鎖。
  • 儘量減少同步的代碼塊。

synchronized的作用?

在Java中,synchronized關鍵字是用來控制線程同步的,就是在多線程的環境下,控制synchronized代碼段不被多個線程同時執行。

synchronized既可以加在一段代碼上,也可以加在方法上。

多線程中 synchronized 鎖升級的原理是什麼?

synchronized 鎖升級原理:在鎖對象的對象頭裏面有一個 threadid 字段,在第一次訪問的時候 threadid 爲空,jvm 讓其持有偏向鎖,並將 threadid 設置爲其線程 id,再次進入的時候會先判斷 threadid 是否與其線程 id 一致,如果一致則可以直接使用此對象,如果不一致,則升級偏向鎖爲輕量級鎖,通過自旋循環一定次數來獲取鎖,執行一定次數之後,如果還沒有正常獲取到要使用的對象,此時就會把鎖從輕量級升級爲重量級鎖,此過程就構成了 synchronized 鎖的升級。

鎖的升級的目的:鎖升級是爲了減低了鎖帶來的性能消耗。在 Java 6 之後優化 synchronized 的實現方式,使用了偏向鎖升級爲輕量級鎖再升級到重量級鎖的方式,從而減低了鎖帶來的性能消耗。

synchronized 底層實現原理?

synchronized 是由一對 monitorenter/monitorexit 指令實現的,monitor 對象是同步的基本實現單元。在 Java 6 之前,monitor 的實現完全是依靠操作系統內部的互斥鎖,因爲需要進行用戶態到內核態的切換,所以同步操作是一個無差別的重量級操作,性能也很低。但在 Java 6 的時候,Java 虛擬機 對此進行了大刀闊斧地改進,提供了三種不同的 monitor 實現,也就是常說的三種不同的鎖:偏向鎖(Biased Locking)、輕量級鎖和重量級鎖,大大改進了其性能。

synchronized 和 volatile 的區別是什麼?

  • volatile 是變量修飾符;synchronized 是修飾類、方法、代碼段。
  • volatile 僅能實現變量的修改可見性,不能保證原子性;而 synchronized 則可以保證變量的修改可見性和原子性。
  • volatile 不會造成線程的阻塞;synchronized 可能會造成線程的阻塞。

synchronized 和 Lock 有什麼區別?

  • synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。
  • synchronized 不需要手動獲取鎖和釋放鎖,使用簡單,發生異常會自動釋放鎖,不會造成死鎖;而 lock 需要自己加鎖和釋放鎖,如果使用不當沒有 unLock()去釋放鎖就會造成死鎖。
  • 通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到。

synchronized 和 ReentrantLock 區別是什麼?

synchronized 早期的實現比較低效,對比 ReentrantLock,大多數場景性能都相差較大,但是在 Java 6 中對 synchronized 進行了非常多的改進。

主要區別如下:

  • ReentrantLock 使用起來比較靈活,但是必須有釋放鎖的配合動作;
  • ReentrantLock 必須手動獲取與釋放鎖,而 synchronized 不需要手動釋放和開啓鎖;
  • ReentrantLock 只適用於代碼塊鎖,而 synchronized 可用於修飾方法、代碼塊等。
  • volatile 標記的變量不會被編譯器優化;synchronized 標記的變量可以被編譯器優化。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章