1. 程式人生 > >java多執行緒面試題

java多執行緒面試題

轉載自https://blog.csdn.net/jjj19891128/article/details/24393661
多執行緒在筆試面試中經常出現,下面列出一些公司的多執行緒筆試面試題。首先是一些概念性的問答題,這些是多執行緒的基礎知識,經常出現在面試中的第一輪面試(我參加2011年騰訊研究院實習生招聘時就被問到了幾個概念性題目)。然後是一些選擇題,這些一般在筆試時出現,雖然不是太難,但如果在選擇題上花費大多時間無疑會對後面的程式設計題造成影響,因此必須迅速的解決掉。最後是綜合題即難一些的問答題或是程式設計題。這種題目當然是最難解決了,要麼會引來面試官的追問,要麼就很容易考慮不周全,因此解決這類題目時一定要考慮全面和細緻。
下面就來看看這三類題目吧。
一。概念性問答題
第一題:執行緒的基本概念、執行緒的基本狀態及狀態之間的關係?
概念:執行緒是程序中執行運算的最小單位,是程序中的一個實體,是被系統獨立排程和分派的基本單位,執行緒自己不擁有系統資源,只擁有一點在執行中必不可少的資源,但它可與同屬一個程序的其它執行緒共享程序所擁有的全部資源。一個執行緒可以建立和撤消另一個執行緒,同一程序中的多個執行緒之間可以併發執行。

好處 :

(1)易於排程。

           (2)提高併發性。通過執行緒可方便有效地實現併發性。程序可建立多個執行緒來執行同一程式的不同部分。

           (3)開銷少。建立執行緒比建立程序要快,所需開銷很少。。

           (4)利於充分發揮多處理器的功能。通過建立多執行緒程序,每個執行緒在一個處理器上執行,從而實現應用程式的併發性,使每個處理器都得到充分執行。

狀態:執行、阻塞、掛起阻塞、就緒、掛起就緒

狀態之間的轉換:準備就緒的程序,被CPU排程執行,變成執行態;

                             執行中的程序,進行I/O請求或者不能得到所請求的資源,變成阻塞態;

                             執行中的程序,程序執行完畢(或時間片已到),變成就緒態;

                             將阻塞態的程序掛起,變成掛起阻塞態,當導致程序阻塞的I/O操作在使用者重啟程序前完成(稱之為喚醒),掛起阻塞態變成掛起就緒態,當用戶在I/O操作結束之前重啟程序,掛起阻塞態變成阻塞態;

                             將就緒(或執行)中的程序掛起,變成掛起就緒態,當該程序恢復之後,掛起就緒態變成就緒態;                

第二題:執行緒與程序的區別?

這個題目問到的概率相當大,計算機專業考研中也常常考到。要想全部答出比較難。
程序和執行緒的關係:
(1)一個執行緒只能屬於一個程序,而一個程序可以有多個執行緒,但至少有一個執行緒。

(2)資源分配給程序,同一程序的所有執行緒共享該程序的所有資源。

(3)處理機分給執行緒,即真正在處理機上執行的是執行緒。

(4)執行緒在執行過程中,需要協作同步。不同程序的執行緒間要利用訊息通訊的辦法實現同步。執行緒是指程序內的一個執行單元,也是程序內的可排程實體.

程序與執行緒的區別:

(1)排程:執行緒作為排程和分配的基本單位,程序作為擁有資源的基本單位

(2)併發性:不僅程序之間可以併發執行,同一個程序的多個執行緒之間也可併發執行

(3)擁有資源:程序是擁有資源的一個獨立單位,執行緒不擁有系統資源,但可以訪問隸屬於程序的資源.

(4)系統開銷:在建立或撤消程序時,由於系統都要為之分配和回收資源,導致系統的開銷明顯大於建立或撤消執行緒時的開銷。

第三題:多執行緒有幾種實現方法,都是什麼?
C++中多執行緒實現方法:
windows下通過api
CreateThread,linux下則常用pthread庫,這些都是最底層的實現,最新的C++11標準裡增加了std::thread多執行緒庫,使用第三方庫的話就更多了,比如boost的thread等等,不推薦使用vc自家的_beginthread,尤其有跨平臺需求的時候。
JAVA中實現多執行緒的方法:
1. 繼承 Thread 類
2. 實現 Runnable 介面再 new Thread(YourRunnableOjbect) 推薦
第四題:多執行緒同步和互斥有幾種實現方法,都是什麼?
2011年迅雷校園招聘時的一面和二面都被問到這個題目,回答的好將會給面試成績加不少分。
執行緒間的同步方法大體可分為兩類:使用者模式和核心模式。顧名思義,核心模式就是指利用系統核心物件的單一性來進行同步,使用時需要切換核心態與使用者態,而使用者模式就是不需要切換到核心態,只在使用者態完成操作。
使用者模式下的方法有:原子操作(例如一個單一的全域性變數),臨界區。核心模式下的方法有:事件,訊號量,互斥量。
第五題:多執行緒同步和互斥有何異同,在什麼情況下分別使用他們?舉例說明。
當有多個執行緒的時候,經常需要去同步這些執行緒以訪問同一個資料或資源。例如,假設有一個程式,其中一個執行緒用於把檔案讀到記憶體,而另一個執行緒用於統計檔案中的字元數。當然,在把整個檔案調入記憶體之前,統計它的計數是沒有意義的。但是,由於每個操作都有自己的執行緒,作業系統會把兩個執行緒當作是互不相干的任務分別執行,這樣就可能在沒有把整個檔案裝入記憶體時統計字數。為解決此問題,你必須使兩個執行緒同步工作。
所謂同步,是指散步在不同程序之間的若干程式片斷,它們的執行必須嚴格按照規定的某種先後次序來執行,這種先後次序依賴於要完成的特定的任務。如果用對資源的訪問來定義的話,同步是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源。

    所謂互斥,是指散佈在不同程序之間的若干程式片斷,當某個程序執行其中一個程式片段時,其它程序就不能執行它們之中的任一程式片段,只能等到該程序執行完這個程式片段後才可以執行。如果用對資源的訪問來定義的話,互斥某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。

 第六題:程序間通訊的方式?

(1)管道(pipe)及有名管道(named pipe):管道可用於具有親緣關係的父子程序間的通訊,有名管道除了具有管道所具有的功能外,它還允許無親緣關係程序間的通訊。

(2)訊號(signal):訊號是在軟體層次上對中斷機制的一種模擬,它是比較複雜的通訊方式,用於通知程序有某事件發生,一個程序收到一個訊號與處理器收到一箇中斷請求效果上可以說是一致的。

(3)訊息佇列(message queue):訊息佇列是訊息的連結表,它克服了上兩種通訊方式中訊號量有限的缺點,具有寫許可權得程序可以按照一定得規則向訊息佇列中新增新資訊;對訊息佇列有讀許可權得程序則可以從訊息佇列中讀取資訊。

(4)共享記憶體(shared memory):可以說這是最有用的程序間通訊方式。它使得多個程序可以訪問同一塊記憶體空間,不同程序可以及時看到對方程序中對共享記憶體中資料得更新。這種方式需要依靠某種同步操作,如互斥鎖和訊號量等。

(5)訊號量(semaphore):主要作為程序之間及同一種程序的不同執行緒之間得同步和互斥手段。

(6)套接字(socket):這是一種更為一般得程序間通訊機制,它可用於網路中不同機器之間的程序間通訊,應用非常廣泛。

二。選擇題
第一題(百度筆試題):
以下多執行緒對int型變數x的操作,哪幾個不需要進行同步:
A.x=y; B. x++; C.++x; D. x=1;
答案參見:http://blog.csdn.net/jjj19891128/article/details/24392229
第二題(阿里巴巴筆試題)
多執行緒中棧與堆是公有的還是私有的
A:棧公有, 堆私有
B:棧公有,堆公有
C:棧私有, 堆公有D:棧私有,堆私有
一般來說棧是私有的
堆是共有的
但是你可以為特定的執行緒建立私有的堆

堆和棧的區別如下:

堆很靈活,但是不安全。對於物件,我們要動態地建立、銷燬,不能說後建立的物件沒有銷燬,先前建立的物件就不能銷燬,那樣的話我們的程式就寸步難行,所以Java中用堆來儲存物件。而一旦堆中的物件被銷燬,我們繼續引用這個物件的話,就會出現著名的 NullPointerException,這就是堆的缺點——錯誤的引用邏輯只有在執行時才會被發現。

棧不靈活,但是很嚴格,是安全的,易於管理。因為只要上面的引用沒有銷燬,下面引用就一定還在,所以,在棧中,上面引用永遠可以通過下面引用來查詢物件,同時如果確認某一區間的內容會一起存在、一起銷燬,也可以上下互相引用。在大部分程式中,都是先定義的變數、引用先進棧,後定義的後進棧,同時,區塊內部的變數、引用在進入區塊時壓棧,區塊結束時出棧,理解了這種機制,我們就可以很方便地理解各種程式語言的作用域的概念了,同時這也是棧的優點——錯誤的引用邏輯在編譯時就可以被發現。

總之,就是變數和物件的引用儲存在棧區中,而物件在儲存在堆中

三。綜合題
第一題(臺灣某防毒軟體公司面試題):
在Windows程式設計中互斥量與臨界區比較類似,請分析一下二者的主要區別。
兩者都可以用於同一程序中不同子執行緒對資源的互斥訪問。

    互斥量是核心物件,因此還可以用於不同程序中子執行緒對資源的互斥訪問。

    互斥量可以很好的解決由於執行緒意外終止資源無法釋放的問題。

第二題:

一個全域性變數tally,兩個執行緒併發執行(程式碼段都是ThreadProc),問兩個執行緒都結束後,tally取值範圍。
inttally = 0;//glable
voidThreadProc()
{
for(int i = 1; i <= 50;i++)
tally += 1;
}
答:[50,100]
第三題(某培訓機構的練習題):
子執行緒迴圈 10次,接著主執行緒迴圈 100次,接著又回到子執行緒迴圈 10次,接著再回到主執行緒又迴圈 100次,如此迴圈50次,試寫出程式碼。
第四題(迅雷筆試題):
編寫一個程式,開啟3個執行緒,這3個執行緒的ID分別為A、B、C,每個執行緒將自己的ID在螢幕上列印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC…依次遞推。
第五題(Google面試題)
有四個執行緒1、2、3、4.執行緒1的功能就是輸出1,執行緒2的功能就是輸出2,以此類推……現在有四個檔案ABCD.初始都為空。現要讓四個檔案呈如下格式:
A:1 2 3 4 1 2…
B:2 3 4 1 2 3…
C:3 4 1 2 3 4…
D:4 1 2 3 4 1…
請設計程式。
下面的第六題與第七題也是在考研中或是程式設計師和軟體設計師認證考試中的熱門試題。
第六題
生產者消費者問題
這是一個非常經典的多執行緒題目,題目大意如下:有一個生產者在生產產品,這些產品將提供給若干個消費者去消費,為了使生產者和消費者能併發執行,在兩者之間設定一個有多個緩衝區的緩衝池,生產者將它生產的產品放入一個緩衝區中,消費者可以從緩衝區中取走產品進行消費,所有生產者和消費者都是非同步方式執行的,但它們必須保持同步,即不允許消費者到一個空的緩衝區中取產品,也不允許生產者向一個已經裝滿產品且尚未被取走的緩衝區中投放產品。
第七題
讀者寫者問題
這也是一個非常經典的多執行緒題目,題目大意如下:有一個寫者很多讀者,多個讀者可以同時讀檔案,但寫者在寫檔案時不允許有讀者在讀檔案,同樣有讀者讀時寫者也不能寫。
多執行緒相關題目就列舉到此,如果各位有多執行緒方面的筆試面試題,歡迎提供給我,我將及時補上。謝謝大家。