全面的多執行緒面試題含答案(37道面試題)
多執行緒面試題:
1.什麼是執行緒,什麼是程序,它們有什麼區別和聯絡,一個程序裡面是否必須有個執行緒
(先講程序)
答案
程序本質上是一個執行的程式,一個程序可以有多個執行緒。它允許計算機同時執行兩個或多個程式。一個程序至少會有一個執行緒。執行緒是程序的最小執行單位。
區別:多程序程式不受Java的控制,而多執行緒則受Java控制。多執行緒比多程序需要更少的管理費用。
2.實現一個執行緒有哪幾種方式,各有什麼優缺點,比較常用的是那種,為什麼
答案
執行緒有3種實現方式:
①.通過繼承Thread類,優點:可以直接呼叫start方法啟動。缺點:繼承一個類後,不能再繼承別的類。需要重寫run方法。無返回值。
②.實現Runnable介面,優點:可以實現多個介面或繼承一個類;缺點:不能直接啟動,要通過構造一個Thread把自己傳進去。需要重寫run方法,無返回值。
③.實現Callable介面,優點:可以丟擲異常,有返回值;缺點:只有jkd1.5以後才支援。需要重寫call方法。結合FutureTask和Thread類一起使用,最後呼叫start啟動。
一般最常用的是第二種,實現Runnable介面。比較方便,可擴充套件性高。
3. 一般情況下我們實現自己執行緒時候要重寫什麼方法
答案
使用Thread類,要重寫run方法,或實現Runnable介面時,要實現run()方法
使用Callable介面時,要重寫call方法,且有返回值。
4.start方法和run方法有什麼區別,我們一般呼叫的那個方法,系統呼叫的是那個方法
答案
start用於啟動執行緒,當呼叫start後,執行緒並不會馬上執行,而是處於就緒狀態,是否要執行取決於cpu給的時間片。
run用於子類重寫來實現執行緒的功能。
我們一般呼叫的是start方法,系統呼叫的是run方法。
5.sleep方法有什麼作用,一般用來做什麼
答案
sleep是一個Thread類的靜態方法,讓呼叫它的執行緒休眠指定的時間,可用於暫停執行緒,但不會把鎖讓給其他執行緒,時間一到,執行緒會繼續執行。
6. 講下join,yield方法的作用,以及什麼場合用它們
答案
join執行緒有嚴格的先後順序,呼叫它的執行緒需要執行完以後其他執行緒才會跟著執行。
yield是暫停當前正在執行的執行緒物件,把時間讓給其他執行緒。
使用場合:join執行緒有嚴格的先後順序,yield當前執行緒佔用cpu使用率很高時,把時間讓出來。(死迴圈時)
7.執行緒中斷是否能直接呼叫stop,為什麼?
答案
不可以,stop方法是從外部強行終止一個執行緒,會導致不可預知的錯誤。如使用IO流時不能關流
8.列舉出一般情況下執行緒中斷的幾種方式,並說明他們之間的優缺點,並且說明那種中斷方式最好
答案
中斷執行緒有4種方式:
①.由interrupt發出中斷訊號,使用者接收中斷訊號,通過isInterrupted判斷執行緒是否中斷。
②.由interrupt發出中斷訊號,系統接收中斷訊號,通過sleep丟擲中斷異常,並把中斷訊號清除,只能丟擲一次。
③.使用者自定義中斷訊號,並將該訊號發出,自己接收該中斷訊號。
④.呼叫interrupted(),會把中斷訊號清除,並中斷執行緒。
9.執行緒有幾種狀態,他們是怎麼轉化的
答案
執行緒一般分為:新生、可執行、執行、阻塞、死亡五種狀態。
當建立一個執行緒後,並沒有執行,還處於新生狀態,需要通過呼叫start方法,讓執行緒處於可執行狀態,但是否執行取決cpu分配的時間片,當得到cpu的時間片後,執行緒就會馬上執行,一個正在執行的執行緒可以通過很多方式進入阻塞狀態(等待輸入/輸出 ,sleep,wait,get)當執行完所有操作後就進入死亡狀態。
10.在實現Runnable的介面中怎麼樣訪問當前執行緒物件,比如拿到當前執行緒的名字
答案
通過currentThread()方法訪問當前執行緒物件,通過getName()可獲得當前執行緒的名字。
11. 講下什麼是守護執行緒,以及在什麼場合來使用它
答案
守護執行緒一般在後臺提供通用性支援,只有非守護執行緒全部退出時,守護執行緒才會退出。
當主執行緒和主執行緒建立的子執行緒全部退出,守護執行緒一定會跟著退出。
12.一般的執行緒優先順序是什麼回事,執行緒優先順序高的執行緒一定會先執行嗎?如果不設定優先順序的話,那麼執行緒優先順序是多少,設定執行緒優先順序用那個函式
答案
執行緒的優先順序就是設定哪個執行緒優先執行,但也不是絕對的,只是讓優先順序高的執行緒優先執行的機率高一些。執行緒預設是NORM_PRIORITY = 5; 設定優先順序使用的是setPriority()函式。
13.為什麼Thread裡面的大部分方法都是final的
答案
不能被重寫,執行緒的很多方法都是由系統呼叫的,不能通過子類覆寫去改變他們的行為。
14.什麼是執行緒同步,什麼是執行緒安全
答案
當兩個或兩個以上的執行緒需要共享資源,他們就需要某種方法來確定資源在某一刻僅被一個執行緒佔用。
執行緒安全就是多執行緒操作同一個物件不會有問題,執行緒同步一般來保護執行緒安全,final修飾的也是執行緒安全
15.講下同步方法和同步塊的區別,以及什麼時候用它們
答案
同步方法就是被synchronized修飾的方法,同步整個方法,且整個方法都會被鎖住,同一時間只有一個執行緒可以訪問該方法。整個業務,缺點:效能差
同步塊就是使用synchronized修飾的程式碼塊,可以同步一小部分程式碼
同步塊越小效能越好,當效能要求比較高時,用同步塊
16.簡單說下Lock物件的實現類的鎖機制和同步方法或同步塊有什麼區別
答案
答:可重入鎖是jdk1.5以後出現的,比同步方法或同步塊更加靈活,可以控制在什麼時候上鎖,什麼時候解鎖,而使用同步塊或同步方法後,必須要等程式碼執行完後才會解鎖。
17. 同步塊裡面的同步監視器是怎麼寫的,預設的同步方法裡面的同步監視器是那個
答案
synchronized(物件){
//程式碼塊
}
預設的同步監視器this
18.講下什麼 是死鎖,死鎖發生的幾個條件是什麼
答案
死鎖就是當有兩個或兩個以上的執行緒都獲得對方的資源,但彼此有不肯放開,處於僵持狀態,此時便造成了死鎖。
條件:兩個或兩個以上的執行緒
同時想要獲取對方的資源,彼此又不肯放開
19.執行緒間是什麼通訊的,通過呼叫幾個方法來互動的
答案
執行緒間是通過相互作用,共同完成一個任務當一個執行緒呼叫wait方法後便進入等待狀態,需要另一執行緒呼叫notify()方法對它進行喚醒。notifyAll可以喚醒所有執行緒,都必須在synchronized方法或synchronized塊裡使用
20.wait,notify,notifyAll在什麼地方使用才有效,他們是那個類的方法
答案
wait ,notify , notifyAll都必須在synchronized修飾的方法或synchronized塊中使用,都屬於Object的方法,可以被所有類繼承,都是final修飾的方法,不能通過子類覆寫去改變他們的行為。
21.wait和sleep有什麼區別和聯絡,他們執行的時候是否都會釋放鎖
答案
wait和sleep都可以使執行緒暫停,但wait必須在synchronized修飾的方法或synchronized塊中使用,wait可以使鎖定解除,而sleep不會解鎖,wait不被喚醒是一直會在等待,而sleep會在休眠時間結束之後便會執行
22.yield,sleep方法有什麼區別和聯絡
答案
yield和sleep都是可以讓執行緒暫停,但yield會暫停當前正在執行的執行緒,把時間片讓給其他執行緒,而sleep雖然也是暫停當前執行緒,但只會暫停指定的時間,不會把同步鎖讓給其他執行緒,時間到了當前執行緒還會繼續執行。
23 .sleep()和wait()的區別。
wait和sleep都可以使執行緒暫停,但wait必須在synchronized修飾的方法或synchronized塊中使用,wait可以使鎖定解除,而sleep不會解鎖,wait不被喚醒是一直會在等待,而sleep會在休眠時間結束之後便會執行
24.執行緒的啟動是哪個方法,呼叫的是哪個方法?
start用於啟動執行緒,當呼叫start後,執行緒並不會馬上執行,而是處於就緒狀態,是否要執行取決於cpu給的時間片。
run用於子類重寫來實現執行緒的功能。
我們一般呼叫的是start方法,系統呼叫的
是run方法。
25.執行緒安全與執行緒不安全的區別
當兩個或兩個以上的執行緒需要共享資源,他們就需要某種方法來確定資源在某一刻僅被一個執行緒佔用。
執行緒安全就是多執行緒操作同一個物件不會有問題,執行緒同步一般來保護執行緒安全,final修飾的也是執行緒安全
26.執行緒的實現方式,執行緒的生命週期等
1.執行緒的生命週期執行緒是一個動態執行的過程,它也有一個從產生到死亡的過程。
(1)生命週期的五種狀態
新建(new Thread)當建立Thread類的一個例項(物件)時,此執行緒進入新建狀態(未被啟動)。
例如:Thread t1=new Thread();
就緒(runnable)執行緒已經被啟動,正在等待被分配給CPU時間片,也就是說此時執行緒正在就緒佇列中排隊等候得到CPU資源。例如:t1.start();
執行(running)執行緒獲得CPU資源正在執行任務(run()方法),此時除非此執行緒自動放棄CPU資源或者有優先順序更高的執行緒進入,執行緒將一直執行到結束。
死亡(dead)
當執行緒執行完畢或被其它執行緒殺死,執行緒就進入死亡狀態,這時執行緒不可能再進入就緒狀態等待執行。
自然終止:正常執行run()方法後終止
異常終止:呼叫stop()方法讓一個執行緒終止執行
堵塞(blocked)
由於某種原因導致正在執行的執行緒讓出CPU並暫停自己的執行,即進入堵塞狀態。
正在睡眠:用sleep(long t) 方法可使執行緒進入睡眠方式。一個睡眠著的執行緒在指定的時間過去可進入就緒狀態。
正在等待:呼叫wait()方法。(呼叫motify()方法回到就緒狀態)
被另一個執行緒所阻塞:呼叫suspend()方法。(呼叫resume()方法恢復)
27.如何處理執行緒不安全問題 有2種解決方法。
1.放在棧裡面的資料都是執行緒安全
2.同步塊,同步關鍵字修飾的都是執行緒安全
3.final修飾的變數都是執行緒安全
4.ThreadLoacl放置的變數可以解決執行緒安全
5.可以考慮JDK5提供的執行緒安全集合和類
第一,是採用原子變數,畢竟執行緒安全問題最根本上是由於全域性變數和靜態變數引起的,只要保證了對於變數的寫操作要麼全寫要麼不寫,就可以解決執行緒安全,定義變數用sig_atomic_t和volatile。
第二,就是實現執行緒間同步啦,用互斥鎖,訊號量。讓執行緒有序的訪問變數就可以啦
28.執行緒中常用方法的區別,
首先,執行緒中最多用到的是start方法,它的作用是用來啟動一個執行緒。(一個Thread類的物件就是一個執行緒,用這個物件.start()就是啟動一個執行緒)
其次,執行緒中用的多的就是sleep,join,wait這種會引發InterruptedException異常的方法,
sleep是用來休眠一個執行緒一段時間,
join是用來強制執行一個執行緒,
wait這個方法是Object類中的方法,用於等待。
除yield(),禮讓的意思就是讓另外一個執行緒執行一會,然後自己再執行,不同於sleep。
還有獲得當前執行緒的物件,這個方法也很重要,currentThread()。
對於執行緒中,還應瞭解到執行緒的死鎖的概念,不需要掌握這個概念,但是應該知道可以通過哪些途徑避免死鎖,java中提供了使用Synchronized關鍵字和Synchronized同步方法來解決。
29.多執行緒和單執行緒有什麼區別?
單執行緒的也就是程式執行時,所跑的程式路徑(處理的東西)是連續順序下來的,必須前面的處理好,後面的彩繪執行到。
多執行緒嘛,舉個例子也就是說程式可以同時執行2個以上相同類似的操作,比如一些搜尋代理或者群發email的多執行緒軟體,由於操作一次需要網路的返回信 息 花的時間比較長,而對cpu來說卻是空閒的,如果是一個一個順序執行,那麼搜尋幾千個IP就會花上好久好久。 而如果用多執行緒就可以在等待期間 加入 其他的搜尋,然後等待,這樣可以提高效率。
30.執行緒的四種狀態,__、 _、 _、 ___。啟動呼叫 _方法,啟動後會呼叫 __方法。
四種狀態:新(new) 可執行(runnable)堵塞(blocked)死(dead)
啟動呼叫start 啟動後呼叫run
31.用同步塊與同步方法的區別?
同步方法就是被synchronized修飾的方法,同步整個方法,且整個方法都會被鎖住,同一時間只有一個執行緒可以訪問該方法。整個業務,缺點:效能差
同步塊就是使用synchronized修飾的程式碼塊,可以同步一小部分程式碼
同步塊越小效能越好,當效能要求比較高時,用同步塊
32.寫二個執行緒,對一個int型別一個i++,一個i--
public class ThreadTest implements Runnable{
ofollow,noindex">@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("我是子執行緒"+i);
}
}
public static void main(String[] args) {
Runnable runnable=new ThreadTest();
Thread thread=new Thread(runnable);
thread.start();
for (int i = 10; i >0; i--) {
System.out.println("我是主執行緒"+i);
}
}
}
34.說說stop為什麼不建議使用 。
stop()方法作為一種粗暴的執行緒終止行為,線上程終止之前沒有對其做任何的清除操作,因此具有固有的不安全性。
35.Runable介面的方法是什麼?
run
什麼是同步和非同步,分別用例子說明,同步有幾種方式?
同步就是排隊去做事情,非同步就是各做各的
36.什麼是物件鎖?
物件鎖。同一時間只保證 一個執行緒訪問方法或變數。
在Java語言中,通過被關鍵字synchronized修飾的方法或synchronized語句塊實現對程式碼的同步
包含在synchronized方法或語句塊中的程式碼稱為被同步的程式碼(Synchronized Code)
當執行緒訪問被同步的程式碼時,必須首先競爭程式碼所屬的類的【物件上的鎖】,否則執行緒將等待(阻塞),直到鎖被釋放.
列子:
同步語句(synchronized statements)的一般形式如下:
synchronized(<鎖物件引用>){
…被同步的程式碼…
}
37.執行緒的死鎖問題
死鎖就是當有兩個或兩個以上的執行緒都獲得對方的資源,但彼此有不肯放開,處於僵持狀態,此時便造成了死鎖。
條件:兩個或兩個以上的執行緒
同時想要獲取對方的資源,彼此又不肯放開
"5.下列哪個是Runable介面的方法()
A.run B.start C.yicld D.stop
"
答:A
寫一個生產者-消費者模型
code...