天天看點

Java程式員面試中的多線程問題

  0、java 中多線程同步是什麼?

  在多線程程式下,同步能控制對共享資源的通路。如果沒有同步,當一個 java 線程在修改一個共享變量時,另外一個線程正在使用或者更新同一個變量,這樣容易導緻程式出現錯誤的結果。

  1、解釋實作多線程的幾種方法?

  一 java 線程可以實作 runnable 接口或者繼承 thread 類來實作,當你打算多重繼承時,優先選擇實作 runnable。

  2、thread.start ()與 thread.run ()有什麼差別?

  thread.start ()方法(native)啟動線程,使之進入就緒狀态,當 cpu 配置設定時間該線程時,由 jvm 排程執行 run ()方法。

Java程式員面試中的多線程問題

  3、為什麼需要 run ()和 start ()方法,我們可以隻用 run ()方法來完成任務嗎?

  4、什麼是 threadlocal 類,怎麼使用它?

  threadlocal 是一個線程級别的局部變量,并非“本地線程”。threadlocal 為每個使用該變量的線程提供了一個獨立的變量副本,每個線程修改副本時不影響其它線程對象的副本(譯者注)。

  下面是線程局部變量(threadlocal variables)的關鍵點:

  一個線程局部變量(threadlocal variables)為每個線程友善地提供了一個單獨的變量。

  threadlocal 執行個體通常作為靜态的私有的(private static)字段出現在一個類中,這個類用來關聯一個線程。

  當多個線程通路 threadlocal 執行個體時,每個線程維護 threadlocal 提供的獨立的變量副本。

  threadlocal 難于了解,下面這些引用連接配接有助于你更好的了解它。

  5、什麼時候抛出 invalidmonitorstateexception 異常,為什麼?

   調用 wait ()/notify ()/notifyall ()中的任何一個方法時,如果目前線程沒有獲得該對象的鎖,那麼就會抛出 illegalmonitorstateexception 的異常(也就是說程式在沒有執行對象的任何同步塊或者同步方法時,仍然嘗試調用 wait ()/notify ()/notifyall ()時)。由于該異常是 runtimeexcpetion 的子類,是以該異常不一定要捕獲(盡管你可以捕獲隻要你願意).作為 runtimeexception,此類異常不會在 wait (),notify (),notifyall ()的方法簽名提及。

6、sleep ()、suspend ()和 wait ()之間有什麼差別?

  thread.sleep ()使目前線程在指定的時間處于“非運作”(not runnable)狀态。線程一直持有對象的螢幕。比如一個線程目前在一個同步塊或同步方法中,其它線程不能進入該塊或方法中。如果另一線程調用了 interrupt ()方法,它将喚醒那個“睡眠的”線程。

  注意:sleep ()是一個靜态方法。這意味着隻對目前線程有效,一個常見的錯誤是調用t.sleep (),(這裡的t是一個不同于目前線程的線程)。即便是執行t.sleep (),也是目前線程進入睡眠,而不是t線程。t.suspend ()是過時的方法,使用 suspend ()導緻線程進入停滞狀态,該線程會一直持有對象的螢幕,suspend ()容易引起死鎖問題。

  object.wait ()使目前線程出于“不可運作”狀态,和 sleep ()不同的是 wait 是 object 的方法而不是 thread。調用 object.wait ()時,線程先要擷取這個對象的對象鎖,目前線程必須在鎖對象保持同步,把目前線程添加到等待隊列中,随後另一線程可以同步同一個對象鎖來調用 object.notify (),這樣将喚醒原來等待中的線程,然後釋放該鎖。基本上 wait ()/notify ()與 sleep ()/interrupt ()類似,隻是前者需要擷取對象鎖。

  7、在靜态方法上使用同步時會發生什麼事?

  同步靜态方法時會擷取該類的“class”對象,是以當一個線程進入同步的靜态方法中時,線程螢幕擷取類本身的對象鎖,其它線程不能進入這個類的任何靜态同步方法。它不像執行個體方法,因為多個線程可以同時通路不同執行個體同步執行個體方法。

  8、當一個同步方法已經執行,線程能夠調用對象上的非同步執行個體方法嗎?

  可以,一個非同步方法總是可以被調用而不會有任何問題。實際上,java 沒有為非同步方法做任何檢查,鎖對象僅僅在同步方法或者同步代碼塊中檢查。如果一個方法沒有聲明為同步,即使你在使用共享資料 java 照樣會調用,而不會做檢查是否安全,是以在這種情況下要特别小心。一個方法是否聲明為同步取決于臨界區通路(critial section access),如果方法不通路臨界區(共享資源或者資料結構)就沒必要聲明為同步的。

  下面有一個示例說明:common 類有兩個方法 synchronizedmethod1()和 method1(),mythread 類在獨立的線程中調用這兩個方法。

public class common {  

public synchronized void synchronizedmethod1() {  

system.out.println ("synchronizedmethod1 called");  

try {  

thread.sleep (1000);  

} catch (interruptedexception e) {  

e.printstacktrace ();  

}  

system.out.println ("synchronizedmethod1 done");  

public void method1() {  

system.out.println ("method 1 called");  

system.out.println ("method 1 done");  

}

public class mythread extends thread {  

private int id = 0;  

private common common;  

public mythread (string name, int no, common object) {  

super(name);  

common = object;  

id = no;  

public void run () {  

system.out.println ("running thread" + this.getname ());  

if (id == 0) {  

common.synchronizedmethod1();  

} else {  

common.method1();  

} catch (exception e) {  

public static void main (string[] args) {  

common c = new common ();  

mythread t1 = new mythread ("mythread-1", 0, c);  

mythread t2 = new mythread ("mythread-2", 1, c);  

t1.start ();  

t2.start ();  

  10、什麼是死鎖

  死鎖就是兩個或兩個以上的線程被無限的阻塞,線程之間互相等待所需資源。這種情況可能發生在當兩個線程嘗試擷取其它資源的鎖,而每個線程又陷入無限等待其它資源鎖的釋放,除非一個使用者程序被終止。就 javaapi 而言,線程死鎖可能發生在一下情況。

  ● 當兩個線程互相調用 thread.join()

  ● 當兩個線程使用嵌套的同步塊,一個線程占用了另外一個線程必需的鎖,互相等待時被阻塞就有可能出現死鎖。

  11、什麼是線程餓死,什麼是活鎖?

  線程餓死和活鎖雖然不想是死鎖一樣的常見問題,但是對于并發程式設計的設計者來說就像一次邂逅一樣。

  當所有線程阻塞,或者由于需要的資源無效而不能處理,不存在非阻塞線程使資源可用。javaapi 中線程活鎖可能發生在以下情形:

  ● 當所有線程在程式中執行 object.wait(0),參數為 0 的 wait 方法。程式将發生活鎖直到在相應的對象上有線程調用 object.notify()或者 object.notifyall()。

  ● 當所有線程卡在無限循環中。

  這裡的問題并不詳盡,我相信還有很多重要的問題并未提及,您認為還有哪些問題應該包括在上面呢?歡迎在評論中分享任何形式的問題與建議。

====================================分割線================================

最新内容請見作者的github頁:http://qaseven.github.io/