Java面試------多執行緒篇
多執行緒篇
一.什麼是執行緒?
執行緒是作業系統能夠進行運算排程的最小單位,它被包含在程序之中,是程序中的實際運作單位。程式設計師可以通過它進行多處理器程式設計,你可以使用多執行緒對運算密集型任務提速。比如,如果一個執行緒完成一個任務要 100 毫秒,那麼用十個執行緒完成改任務只需 10 毫秒。
二.什麼是程序?
執行緒是程序的子集,一個程序可以有很多執行緒,每條執行緒並行執行不同的任務。不同的程序使用不同的記憶體空間,而所有的執行緒共享一片相同的記憶體空間。
三.在Java中如何試下多執行緒?
在語言層面有兩種方式。java.lang.Thread 類的例項就是一個執行緒但是它需要呼叫 java.lang.Runnable 介面來執行,由於執行緒類本身就是呼叫的 Runnable 介面所以你可以繼承 java.lang.Thread 類或者直接呼叫 Runnable 介面來重寫 run ()方法實現執行緒。
四.用Thread的好還是Runnable?
如果你知道 Java 不支援類的多重繼承,但允許你呼叫多個介面。所以如果你要繼承其他類,當然是呼叫 Runnable 介面好了。
五.Thread 類中的 start () 和 run () 方法有什麼區別?
start ()方法被用來啟動新建立的執行緒,而且 start ()內部呼叫了 run ()方法,這和直接呼叫 run ()方法的效果不一樣。當你呼叫 run ()方法的時候,只會是在原來的執行緒中呼叫,沒有新的執行緒啟動,start ()方法才會啟動新執行緒。
六.如何在兩個執行緒間共享資料?
可以通過共享物件來實現這個目的,或者是使用像阻塞佇列這樣併發的資料結構。用 wait 和 notify 方法實現了生產者消費者模型。
七.Java 中 notify 和 notifyAll 有什麼區別?
因為多執行緒可以等待單監控鎖,Java API 的設計人員提供了一些方法當等待條件改變的時候通知它們,但是這些方法沒有完全實現。notify ()方法不能喚醒某個具體的執行緒,所以只有一個執行緒在等待的時候它才有用武之地。而 notifyAll ()喚醒所有執行緒並允許他們爭奪鎖確保了至少有一個執行緒能繼續執行。
八.為什麼 wait 和 notify 方法要在同步塊中呼叫?
主要是因為 Java API 強制要求這樣做,如果你不這麼做,你的程式碼會丟擲 IllegalMonitorStateException 異常。還有一個原因是為了避免 wait 和 notify 之間產生競態條件。
九.什麼是執行緒池? 為什麼要使用它?
建立執行緒要花費昂貴的資源和時間,如果任務來了才建立執行緒那麼響應時間會變長,而且一個程序能建立的執行緒數有限。為了避免這些問題,在程式啟動的時候就建立若干執行緒來響應處理,它們被稱為執行緒池,裡面的執行緒叫工作執行緒。從 JDK1.5 開始,Java API 提供了 Executor 框架讓你可以建立不同的執行緒池。比如單執行緒池,每次處理一個任務;數目固定的執行緒池或者是快取執行緒池(一個適合很多生存期短的任務的程式的可擴充套件執行緒池)。
十.如何避免死鎖?
Java 多執行緒中的死鎖
死鎖是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。這是一個嚴重的問題,因為死鎖會讓你的程式掛起無法完成任務,死鎖的發生必須滿足以下四個條件:
互斥條件:一個資源每次只能被一個程序使用。
請求與保持條件:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。
不剝奪條件:程序已獲得的資源,在末使用完之前,不能強行剝奪。
迴圈等待條件:若干程序之間形成一種頭尾相接的迴圈等待資源關係。
避免死鎖最簡單的方法就是阻止迴圈等待條件,將系統中所有的資源設定標誌位、排序,規定所有的程序申請資源必須以一定的順序(升序或降序)做操作來避免死鎖。
十一.有三個執行緒 T1,T2,T3,怎麼確保它們按順序執行?
在多執行緒中有多種方法讓執行緒按特定順序執行,你可以用執行緒類的 join ()方法在一個執行緒中啟動另一個執行緒,另外一個執行緒完成該執行緒繼續執行。為了確保三個執行緒的順序你應該先啟動最後一個(T3 呼叫 T2,T2 呼叫 T1),這樣 T1 就會先完成而 T3 最後完成。