1. 程式人生 > >多執行緒經典面試題和答案

多執行緒經典面試題和答案

Java實現執行緒有哪幾種方式?

1、繼承Thread類實現多執行緒
2、實現Runnable介面方式實現多執行緒
3、使用ExecutorService、Callable、Future實現有返回結果的多執行緒

 

 

 

多執行緒同步有哪幾種方法?


Synchronized關鍵字,Lock鎖實現,分散式鎖等。

 

 

 

Runnable和Thread用哪個好?

Java不支援類的多重繼承,但允許你實現多個介面。所以如果你要繼承其他類,也為了減少類之間的耦合性,Runnable會更好。

 

 

 

Java中notify和notifyAll有什麼區別?

notify()方法不能喚醒某個具體的執行緒,所以只有一個執行緒在等待的時候它才有用武之地。而notifyAll()喚醒所有執行緒並允許他們爭奪鎖確保了至少有一個執行緒能繼續執行。

 

 

 

為什麼wait/notify/notifyAll這些方法不在thread類裡面?

這是個設計相關的問題,它考察的是面試者對現有系統和一些普遍存在但看起來不合理的事物的看法。回答這些問題的時候,你要說明為什麼把這些方法放在Object類裡是有意義的,還有不把它放在Thread類裡的原因。一個很明顯的原因是JAVA提供的鎖是物件級的而不是執行緒級的,每個物件都有鎖,通過執行緒獲得。如果執行緒需要等待某些鎖那麼呼叫物件中的wait()方法就有意義了。如果wait()方法定義在Thread類中,執行緒正在等待的是哪個鎖就不明顯了。簡單的說,由於wait,notify和notifyAll都是鎖級別的操作,所以把他們定義在Object類中因為鎖屬於物件。

為什麼wait和notify方法要在同步塊中呼叫?

主要是因為Java API強制要求這樣做,如果你不這麼做,你的程式碼會丟擲IllegalMonitorStateException異常。還有一個原因是為了避免wait和notify之間產生競態條件。

 

 

 

什麼是死鎖?如何避免死鎖?

死鎖就是兩個執行緒相互等待對方釋放物件鎖。

 

 

啟動執行緒方法start()和run()有什麼區別?

只有呼叫了start()方法,才會表現出多執行緒的特性,不同執行緒的run()方法裡面的程式碼交替執行。如果只是呼叫run()方法,那麼程式碼還是同步執行的,必須等待一個執行緒的run()方法裡面的程式碼全部執行完畢之後,另外一個執行緒才可以執行其run()方法裡面的程式碼。

 

 

多執行緒之間如何進行通訊?

wait/notify

 

什麼是執行緒池?

很簡單,簡單看名字就知道是裝有執行緒的池子,我們可以把要執行的多執行緒交給執行緒池來處理,和連線池的概念一樣,通過維護一定數量的執行緒池來達到多個執行緒的複用。

 

執行緒池的好處

我們知道不用執行緒池的話,每個執行緒都要通過new Thread(xxRunnable).start()的方式來建立並執行一個執行緒,執行緒少的話這不會是問題,而真實環境可能會開啟多個執行緒讓系統和程式達到最佳效率,當執行緒數達到一定數量就會耗盡系統的CPU和記憶體資源,也會造成GC頻繁收集和停頓,因為每次建立和銷燬一個執行緒都是要消耗系統資源的,如果為每個任務都建立執行緒這無疑是一個很大的效能瓶頸。所以,執行緒池中的執行緒複用極大節省了系統資源,當執行緒一段時間不再有任務處理時它也會自動銷燬,而不會長駐記憶體。


什麼是活鎖、飢餓、無鎖、死鎖?

死鎖、活鎖、飢餓是關於多執行緒是否活躍出現的執行阻塞障礙問題,如果執行緒出現了這三種情況,即執行緒不再活躍,不能再正常地執行下去了。

 

死鎖

死鎖是多執行緒中最差的一種情況,多個執行緒相互佔用對方的資源的鎖,而又相互等對方釋放鎖,此時若無外力干預,這些執行緒則一直處理阻塞的假死狀態,形成死鎖。

 

舉個例子,A同學搶了B同學的鋼筆,B同學搶了A同學的書,兩個人都相互佔用對方的東西,都在讓對方先還給自己自己再還,這樣一直爭執下去等待對方還而又得不到解決,老師知道此事後就讓他們相互還給對方,這樣在外力的干預下他們才解決,當然這只是個例子沒有老師他們也能很好解決,計算機不像人如果發現這種情況沒有外力干預還是會一直阻塞下去的。

 

活鎖

活鎖這個概念大家應該很少有人聽說或理解它的概念,而在多執行緒中這確實存在。活鎖恰恰與死鎖相反,死鎖是大家都拿不到資源都佔用著對方的資源,而活鎖是拿到資源卻又相互釋放不執行。當多執行緒中出現了相互謙讓,都主動將資源釋放給別的執行緒使用,這樣這個資源在多個執行緒之間跳動而又得不到執行,這就是活鎖。

 

飢餓

我們知道多執行緒執行中有執行緒優先順序這個東西,優先順序高的執行緒能夠插隊並優先執行,這樣如果優先順序高的執行緒一直搶佔優先順序低執行緒的資源,導致低優先順序執行緒無法得到執行,這就是飢餓。當然還有一種飢餓的情況,一個執行緒一直佔著一個資源不放而導致其他執行緒得不到執行,與死鎖不同的是飢餓在以後一段時間內還是能夠得到執行的,如那個佔用資源的執行緒結束了並釋放了資源。

 

無鎖

無鎖,即沒有對資源進行鎖定,即所有的執行緒都能訪問並修改同一個資源,但同時只有一個執行緒能修改成功。無鎖典型的特點就是一個修改操作在一個迴圈內進行,執行緒會不斷的嘗試修改共享資源,如果沒有衝突就修改成功並退出否則就會繼續下一次迴圈嘗試。所以,如果有多個執行緒修改同一個值必定會有一個執行緒能修改成功,而其他修改失敗的執行緒會不斷重試直到修改成功。之前的文章我介紹過JDK的CAS原理及應用即是無鎖的實現。

 

可以看出,無鎖是一種非常良好的設計,它不會出現執行緒出現的跳躍性問題,鎖使用不當肯定會出現系統性能問題,雖然無鎖無法全面代替有鎖,但無鎖在某些場合下是非常高效的。

 

 

Synchronized有哪幾種用法?

鎖類、鎖方法、鎖程式碼塊。

 

Fork/Join框架是幹什麼的?

 

大任務自動分散小任務,併發執行,合併小任務結果。

 

Java中用到了什麼執行緒排程演算法?

 

搶佔式。一個執行緒用完CPU之後,作業系統會根據執行緒優先順序、執行緒飢餓情況等資料算出一個總的優先順序並分配下一個時間片給某個執行緒執行。

轉載: http://youzhixueyuan.com/the-most-multithreaded-interview-questions-and-answers.html

 

 

本文轉載標題:最全多執行緒經典面試題和答案 頁面地址:http://youzhixueyuan.com/the-most-multithreaded-interview-questions-and-answers.htm