java面試題---多線程

  1. 並行和併發有什麼區別?
    併發:指在同一時刻做不止一件事情。
    並行:指將大量的任務,拆解成多個子任務分配到多個線程上,併發的執行。

  2. 線程和進程的區別?
    進程是資源分配的最小單位,線程是程序執行的最小單位
    進程有自己的獨立地址空間,而線程是共享進程中的數據的,使用相同的地址空間。
    多進程程序更健壯,多線程程序只要有一個線程死掉,整個進程也死掉了,而一個進程死掉並不會對另外一個進程造成影響。

  3. 守護線程是什麼?
    守護線程(即daemon thread),是個服務線程,準確地來說就是服務其他的線程,這是它的作用——而其他的線程只有一種,那就是用戶線程。所以java裏線程分2種:
    1、守護線程,比如垃圾回收線程,就是最典型的守護線程。
    2、用戶線程,就是應用程序裏的自定義線程。

  4. 創建線程有哪幾種方式?
    繼承Thread類創建線程類
    通過Runnable接口創建線程類
    通過Callable和FutureTask創建線程
    通過線程池創建線程

  5. 說一下 runnable 和 callable 有什麼區別?
    實現Callable接口的任務線程能返回執行結果;而實現Runnable接口的任務線程不能返回結果;
    Callable接口的call()方法允許拋出異常;而Runnable接口的run()方法的異常只能在內部消化,不能繼續上拋;

  6. 線程有哪些狀態?
    新建狀態、就緒狀態、運行狀態、阻塞狀態、死亡狀態

  7. sleep() 和 wait() 有什麼區別?
    sleep()是線程線程類(Thread)的方法
    wait()是Object的方法
    sleep方法只讓出了CPU,而並不會釋放同步資源鎖
    wait()方法則是指當前線程釋放同步資源鎖,只有調用了notify()方法才能喚醒。

  8. notify()和 notifyAll()有什麼區別?
    notify():喚醒一個處於等待狀態的線程
    notifyAll():喚醒所有處入等待狀態的線程;

  9. 線程的 run()和 start()有什麼區別?
    start()方法來啓動線程。這時此線程是處於就緒狀態, 並沒有運行。 然後通過此Thread類調用方法run()來完成其運行操作的。
    run()方法當作普通方法的方式調用。

  10. 創建線程池有哪幾種方式?
    newSingleThreadExecutor、newFixedThreadPool、newCachedThreadPool、newScheduledThreadPool

  11. 線程池都有哪些狀態?
    線程池的5種狀態:Running、ShutDown、Stop、Tidying、Terminated

  12. 線程池中 submit()和 execute()方法有什麼區別?
    submit()方法,可以提供Future 類型的返回值,不會拋出異常,入參可以爲Callable。
    executor()方法,無返回值,會拋出異常,入參Runnable。

  13. 在 java 程序中怎麼保證多線程的運行安全?
    保證三要素:
    原子性(Synchronized, Lock)
    有序性(Volatile,Synchronized, Lock)
    可見性(Volatile,Synchronized,Lock)

  14. 多線程鎖的升級原理是什麼?
    線程在執行同步塊之前,JVM會先在當前線程的棧楨中創建用於存儲鎖記錄的空間,並將對象頭中的Mark Word複製到鎖記錄中,官方稱爲Displaced Mark Word。然後線程嘗試使用CAS將對象頭中的Mark Word替換爲指向鎖記錄的指針。如果成功,當前線程獲得鎖,如果失敗,則自旋獲取鎖,當自旋獲取鎖仍然失敗時,表示存在其他線程競爭鎖(兩條或兩條以上的線程競爭同一個鎖),則輕量級鎖會膨脹成重量級鎖

  15. 什麼是死鎖?
    線程死鎖是指由於兩個或者多個線程互相持有對方所需要的資源,導致這些線程處於等待狀態,無法前往執行。

  16. 怎麼防止死鎖?
    互斥條件、請求與保持條件、不可剝奪條件、循環等待條件 破壞其中一個條件即可

  17. ThreadLocal 是什麼?有哪些使用場景?
    ThreadLocal是用來維護本線程的變量的,並不能解決共享變量的併發問題。ThreadLocal是各線程將值存入該線程的map中,以ThreadLocal自身作爲key,需要用時獲得的是該線程之前存入的值。如果存入的是共享變量,那取出的也是共享變量,併發問題還是存在的。
    ThreadLocal的主要用途是爲了保持線程自身對象和避免參數傳遞,主要適用場景是按線程多實例(每個線程對應一個實例)的對象的訪問,並且這個對象很多地方都要用到。

  18. 說一下 synchronized 底層實現原理?
    synrhronized關鍵字簡潔、清晰、語義明確,因此即使有了Lock接口,使用的還是非常廣泛。其應用層的語義是可以把任何一個非null 對象 作爲"鎖",當synchronized作用在方法上時,鎖住的便是對象實例(this);當作用在靜態方法時鎖住的便是對象對應的Class實例,因爲 Class數據存在於永久帶,因此靜態方法鎖相當於該類的一個全局鎖;當synchronized作用於某一個對象實例時,鎖住的便是對應的代碼塊。

  19. synchronized 和 volatile 的區別是什麼?
    volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
    volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
    volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性
    volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
    volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化

  20. synchronized 和 Lock 有什麼區別?
    1.首先synchronized是java內置關鍵字,在jvm層面,Lock是個java類;
    2.synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖;
    3.synchronized會自動釋放鎖(a 線程執行完同步代碼會釋放鎖 ;b 線程執行過程中發生異常會釋放鎖),Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖;
    4.用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會一直等待下去,而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了;
    5.synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平(兩者皆可)
    6.Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題。

  21. synchronized 和 ReentrantLock 區別是什麼?
    1 Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現;
    2 synchronized在發生異常時,會自動釋放線程佔有的鎖,因此不會導致死鎖現象發生;而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,因此使用Lock時需要在finally塊中釋放鎖;
    3 Lock可以讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,等待的線程會一直等待下去,不能夠響應中斷;
    4 通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。
    5 Lock可以提高多個線程進行讀操作的效率。

  22. 說一下 atomic 的原理?
    Atomic包是java.util.concurrent下的另一個專門爲線程安全設計的Java包,包含多個原子操作類。這個包裏面提供了一組原子變量類。其基本的特性就是在多線程環境下,當有多個線程同時執行這些類的實例包含的方法時,具有排他性,即當某個線程進入方法,執行其中的指令時,不會被其他線程打斷,而別的線程就像自旋鎖一樣,一直等到該方法執行完成,才由JVM從等待隊列中選擇一個另一個線程進入,這只是一種邏輯上的理解。實際上是藉助硬件的相關指令來實現的,不會阻塞線程(或者說只是在硬件級別上阻塞了)。可以對基本數據、數組中的基本數據、對類中的基本數據進行操作。原子變量類相當於一種泛化的volatile變量,能夠支持原子的和有條件的讀-改-寫操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章