天天看點

java并發多線程面試題和答案

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/u010741376/article/details/46427235

1.java中有幾種方法可以實作一個線程?

兩種,一種是實作Runnable接口,另一種是繼承Thread

2.如何停止一個正在運作的線程?

  this.stop()方法結束線程。

3.notify()和notifyAll()有什麼差別?

   notifyAll使所有原來在該對象上等待被notify的線程統統退出wait的狀态,變成等待該對象上的鎖,一旦該對象被解鎖,他們就會去競争。

   notify則文明得多他隻是選擇一個wait狀态線程進行通知,并使它獲得該對象上的鎖,但不驚動其他同樣在等待被該對象notify的線程們,

   當第一個線程運作完畢以後釋放對象上的鎖此時如果該對象沒有再次使用notify語句,則即便該對象已經空閑,其他wait狀态等待的線程由于沒有得到該對象的通知,繼續處在wait狀态,直到這個對象發出一個notify或notifyAll,它們等待的是被notify或notifyAll,而不是鎖。

   void notify(): 喚醒一個正在等待該對象的線程。

   void notifyAll(): 喚醒所有正在等待該對象的線程。

4.sleep()和 wait()有什麼差別?

    1.這兩個方法來自不同的類分别是Thread和Object

  2、最主要是sleep方法沒有釋放鎖,而 wait 方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法。

  3、wait,notify和notifyAll隻能在同步控制方法或者同步控制塊裡面使用,而sleep可以在任何地方使用(使用範圍)

  synchronized(x){

       x.notify()

       //或者wait()

  }

  4、sleep必須捕獲異常,而wait,notify和notifyAll不需要捕獲異常

5.什麼是Daemon線程?它有什麼意義?

  守護線程是一種“在背景提供通用性支援”的線程,它并不屬于程式本體。

從字面上我們很容易将守護線程了解成是由虛拟機(virtual machine)在内部建立的,而使用者線程則是自己所建立的。事實并不是這樣,任何線程都可以是“守護線程Daemon”或“使用者線程User”。他們在幾乎每個方面都是相同的,唯一的差別是判斷虛拟機何時離開:

使用者線程:Java虛拟機在它所有非守護線程已經離開後自動離開。

守護線程:守護線程則是用來服務使用者線程的,如果沒有其他使用者線程在運作,那麼就沒有可服務對象,也就沒有理由繼續下去。

setDaemon(boolean on)方法可以友善的設定線程的Daemon模式,true為Daemon模式,false為User模式。

setDaemon(boolean on)方法必須線上程啟動之前調用,當線程正在運作時調用會産生異常。

isDaemon方法将測試該線程是否為守護線程。值得一提的是,當你在一個守護線程中産生了其他線程,那麼這些新産生的線程不用設定Daemon屬性,都将是守護線程,使用者線程同樣。

6.java如何實作多線程之間的通訊和協作?

   當使用synchronized 來修飾某個共享資源時(分同步代碼塊和同步方法兩種情況),當某個線程獲得共享資源的鎖後就可以執行相應的代碼段,直到該線程運作完該代碼段後才釋放對該 共享資源的鎖,讓其他線程有機會執行對該共享資源的修改。

   當某個線程占有某個共享資源的鎖時,如果另外一個線程也想獲得這把鎖運作就需要使用wait() 和notify()/notifyAll()方法來進行線程通訊了。

7.什麼是可重入鎖(ReentrantLock)?

    重入鎖(ReentrantLock)是一種遞歸無阻塞的同步機制

8.當一個線程進入某個對象的一個synchronized的執行個體方法後,其它線程是否可進入此對象的其它方法?

    可以進入其他非synchronized的方法,synchronized的方法不可以的!

    Java中的每個對象都有一個鎖(lock)或者叫做螢幕(monitor),當通路某個對象的synchronized方法時,表示的将該對象上鎖,此時其他任何線程都無法再去通路該synchronized方法了,直到之前的那個線程執行方法完畢後(或者是抛出了異常),才将該對象的鎖釋放掉,其他線程才有可能再去通路該synchronized方法。

如果一個對象有多個synchronized方法,某一時刻某個線程已經進入到了某個synchronized方法,那麼在該方法沒有執行完畢前,其他線程是無法通路該對象的任何synchronized方法的

9.synchronized和java.util.concurrent.locks.Lock的異同?

   1.Lock能完成幾乎所有synchronized的功能,并有一些後者不具備的功能,如鎖投票、定時鎖等候、可中斷鎖等候等

   2.synchronized 是Java 語言層面的,是内置的關鍵字;Lock 則是JDK 5中出現的一個包,在使用時,synchronized 同步的代碼塊可以由JVM自動釋放;Lock 需要程式員在finally塊中手工釋放,如果不釋放,可能會引起難以預料的後果(在多線程環境中)。

10.樂觀鎖和悲觀鎖的了解及如何實作,有哪些實作方式?

樂觀鎖是假設我已經拿到鎖,悲觀所是我必須拿到鎖,前者用CAS,後者用mutex。

11.SynchronizedMap和ConcurrentHashMap有什麼差別?

  後者具有更高的并發。

12.CopyOnWriteArrayList可以用于什麼應用場景?

  CopyOnWriteArrayList适合使用在讀操作遠遠大于寫操作的場景裡,比如緩存。

13.什麼叫線程安全?servlet是線程安全嗎?

   如果你的代碼所在的程序中有多個線程在同時運作,而這些線程可能會同時運作這段代碼。如果每次運作結果和單線程運作的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。

   Servlet的線程安全問題隻有在大量的并發通路時才會顯現出來,并且很難發現,是以在編寫Servlet程式時要特别注意。線程安全問題主要是由執行個體變量造成的,是以在Servlet中應避免使用執行個體變量。如果應用程式設計無法避免使用執行個體變量,那麼使用同步來保護要使用的執行個體變量,但為保證系統的最佳性能,應該同步可用性最小的代碼路徑。

 14.同步有幾種實作方法?

   同步有兩種方法。一種同步方法,一種同步代碼!分别是synchronized,wait與notify

 15.volatile有什麼用?能否用一句話說明下volatile的應用場景?

   Volatile 變量具有 synchronized 的可見性特性,但是不具備原子特性。可以被看作是一種 “程度較輕的 synchronized”;與 synchronized 塊相比,volatile 變量所需的編碼較少,并且運作時開銷也較少,但是它所能實作的功能也僅是 synchronized 的一部分。

          您隻能在有限的一些情形下使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:

                          A. 對變量的寫操作不依賴于目前值。

                          B. 該變量沒有包含在具有其他變量的不變式中。

  16.請說明下java的記憶體模型及其工作流程。

   Java把記憶體劃分成兩種:一種是棧記憶體,一種是堆記憶體。

          棧記憶體:存放對象:函數中基本類型的變量和對象的引用變量、靜态類方法 ;特點:棧有一個很重要的特殊性,就是存在棧中的資料可以共享。

         堆記憶體:存放對象:用來存放由new建立的對象和數組;特點:在堆中配置設定的記憶體,由Java虛拟機的自動垃圾回收器來管理。

          java 記憶體模型 ( java memory model ):根據Java Language Specification中的說明, jvm系統中存在一個主記憶體(Main Memory或Java Heap Memory),Java中所有對象成員變量都儲存在主存中,對于所有線程都是共享的。每條線程都有自己的工作記憶體(Working Memory),工作記憶體中儲存的是主存中某些對象成員變量的拷貝,線程對所有對象成員變量的操作都是在工作記憶體中進行,線程之間無法互相直接通路,變量傳遞均需要通過主存完成。

                (1) 擷取對象螢幕的鎖(lock)

                (2) 清空工作記憶體資料, 從主存複制對象成員變量到目前工作記憶體, 即同步資料 (read and load)

                (3) 執行代碼,改變共享變量值 (use and assign)

                (4) 将工作記憶體資料刷回主存 (store and write)

                (5) 釋放對象螢幕的鎖 (unlock)

  17.為什麼代碼會重排序?

    編譯器旨在提升性能。