搜尋
首頁JavaJava面試題java的多執行緒常見面試題

java的多執行緒常見面試題

Dec 24, 2019 pm 03:02 PM
java

java的多執行緒常見面試題

並行和並發有什麼差別?                      (建議學習:java常見面試題

並行是指兩個或多個事件在同一時刻發生;而並發是指兩個或多個事件在同一時刻同一時刻發生;時間間隔發生。

並行是在不同實體上的多個事件,並發是在同一實體上的多個事件。

在一台處理器上「同時」處理多個任務,在多台處理器上同時處理多個任務。如hadoop分散式集群。

所以並發程式設計的目標是充分的利用處理器的每一個核,以達到最高的處理效能。

執行緒和行程的差別?

簡而言之,進程是程式運作和資源分配的基本單位,一個程式至少有一個行程,一個行程至少有一個執行緒。進程在執行過程中擁有獨立的記憶體單元,而多個執行緒共享記憶體資源,減少切換次數,進而效率更高。

執行緒是進程的一個實體,是cpu調度和分派的基本單位,是比程式更小的能獨立運作的基本單位。同一進程中的多個執行緒之間可以並發執行。

守護線程是什麼?

守護線程(即daemon thread),是個服務線程,準確地說就是服務其他的線程。

建立執行緒有哪幾種方式?

①. 繼承Thread類別建立執行緒類別

定義Thread類別的子類,並重寫該類別的run方法,該run方法的方法體就代表了執行緒要完成的任務。因此把run()方法稱為執行體。

建立Thread子類別的實例,即建立了執行緒物件。

呼叫執行緒物件的start()方法來啟動該執行緒。

②. 透過Runnable介面建立執行緒類別

#定義runnable介面的實作類,並重寫該介面的run()方法,該run()方法的方法體同樣是該執行緒的線程執行體。

建立 Runnable實作類別的實例,並依此實例作為Thread的target來建立Thread對象,該Thread對象才是真正的執行緒對象。

呼叫執行緒物件的start()方法來啟動該執行緒。

③. 透過Callable和Future建立執行緒

建立Callable介面的實作類,並實作call()方法,該call()方法將作為執行緒執行體,並且有傳回值。

建立Callable實作類別的實例,使用FutureTask類別來包裝Callable對象,該FutureTask物件封裝了該Callable物件的call()方法的傳回值。

使用FutureTask物件作為Thread物件的target建立並啟動新執行緒。

呼叫FutureTask物件的get()方法來取得子執行緒執行結束後的回傳值。

說一下 runnable 和 callable 有什麼不同?

有點深的問題了,也看出一個Java程式設計師學習知識的廣度。

Runnable介面中的run()方法的回傳值是void,它所做的事情只是純粹地去執行run()方法中的程式碼而已;

Callable介面中的call( )方法是有回傳值的,是一個泛型,和Future、FutureTask配合可以用來得到非同步執行的結果。

執行緒有哪些狀態?

執行緒通常都有五種狀態,建立、就緒、執行、阻塞和死亡。

建立狀態。在產生線程對象,並沒有呼叫該對象的start方法,這是線程處於創建狀態。

就緒狀態。當呼叫了線程物件的start方法之後,該線程就進入了就緒狀態,但是此時線程調度程序還沒有把該線程設定為當前線程,此時處於就緒狀態。在執行緒運行之後,從等待或睡眠回來之後,也會處於就緒狀態。

運行狀態。線程調度程序將處於就緒狀態的線程設定為當前線程,此時線程就進入了運行狀態,開始運行run函數當中的程式碼。

阻塞狀態。執行緒正在運作的時候,被暫停,通常是為了等待某個時間的發生(比如說某項資源就緒)之後再繼續運作。 sleep,suspend,wait等方法都可以導致執行緒阻塞。

死亡狀態。如果一個執行緒的run方法執行結束或呼叫stop方法後,該執行緒就會死亡。對於已經死亡的線程,無法再使用start方法令其進入就緒   

sleep() 和 wait() 有什麼區別?

sleep():方法是線程類別(Thread)的靜態方法,讓呼叫線程進入睡眠狀態,讓出執行機會給其他線程,等到休眠時間結束後,線程進入就緒狀態和其他執行緒一起競爭cpu的執行時間。

因為sleep() 是static靜態的方法,他不能改變物件的機鎖,當一個synchronized區塊中呼叫了sleep() 方法,線程雖然進入休眠,但是物件的機鎖沒有被釋放,其他執行緒依然無法存取這個物件。

wait():wait()是Object類別的方法,當一個執行緒執行到wait方法時,它就進入一個和該物件相關的等待池,同時釋放物件的機鎖,使得其他執行緒能夠訪問,可以透過notify,notifyAll方法來喚醒等待的線程

notify()和notifyAll()有什麼區別?

如果執行緒呼叫了物件的 wait()方法,那麼執行緒就會處於該物件的等待池中,等待池中的執行緒不會去競爭該物件的鎖定。

當有執行緒呼叫了物件的notifyAll()方法(喚醒所有wait 執行緒)或notify()方法(只隨機喚醒一個wait 執行緒),被喚醒的執行緒就會進入該物件的鎖定池中,鎖定池中的執行緒會去競爭該物件鎖定。

也就是說,呼叫了notify後只要一個執行緒會由等待池進入鎖定池,而notifyAll會將該物件等待池內的所有執行緒移到鎖定池中,等待鎖定競爭。

優先順序高的執行緒競爭到物件鎖的機率大,假若某執行緒沒有競爭到該物件鎖,它還會留在鎖定池中,只有執行緒再次呼叫wait()方法,它才會重新回到等待池中。

而競爭到物件鎖定的執行緒則繼續往下執行,直到執行了 synchronized 程式碼區塊,它會釋放掉該物件鎖定,這時鎖定池中的執行緒會繼續競爭該物件鎖定。

線程的 run()和 start()有什麼差別?

每個執行緒都是透過某個特定Thread物件所對應的方法run()來完成其操作的,方法run()稱為執行緒體。透過呼叫Thread類別的start()方法來啟動一個執行緒。

start()方法來啟動一個線程,真正實作了多執行緒運行。這時無需等待run方法體程式碼執行完畢,可以直接繼續執行下面的程式碼; 這時此執行緒是處於就緒狀態, 並沒有執行。

然後透過此Thread類別呼叫方法run()來完成其運行狀態, 這裡方法run()稱為線程體,它包含了要執行的這個線程的內容, Run方法運行結束, 此線程終止。然後CPU再調度其它線程。

run()方法是在本執行緒裡的,只是執行緒裡的一個函數,而不是多執行緒的。如果直接呼叫run(),其實就相當於是呼叫了一個普通函數而已,直接待用run()方法必須等待run()方法執行完畢才能執行下面的程式碼,所以執行路徑還是只有一條,根本就沒有線程的特徵,所以在多執行緒執行時要使用start()方法而不是run()方法。

建立線程池有哪幾種方式?

①. newFixedThreadPool(int nThreads)

建立一個固定長度的線程池,每當提交一個任務就建立一個線程,直到達到線程池的最大數量,這時線程規模將不再變化,當線程發生未預期的錯誤而結束時,線程池會補充一個新的線程。

②. newCachedThreadPool()

建立一個可快取的線程池,如果線程池的規模超過了處理需求,將自動回收空閒線程,而當需求增加時,則可以自動新增線程,線程池的規模不存在任何限制。

③. newSingleThreadExecutor()

這是一個單執行緒的Executor,它建立單一工作執行緒來執行任務,如果這個執行緒異常結束,會建立一個新的來替代它;它的特點是能確保依照任務在佇列中的順序來串列執行。

④. newScheduledThreadPool(int corePoolSize)

建立了一個固定長度的執行緒池,而且以延遲或定時的方式來執行任務,類似於Timer。

執行緒池都有哪些狀態?

執行緒池有5種狀態:Running、ShutDown、Stop、Tidying、Terminated。

執行緒池各個狀態切換框架圖:

java的多執行緒常見面試題

#執行緒池中submit()和execute()方法有什麼區別?

接收的參數不一樣

submit有回傳值,而execute沒有

submit方便Exception處理

在java 程序中怎麼保證多執行緒的運作安全?

線程安全在三個方面體現:

原子性:提供互斥訪問,同一時刻只能有一個線程對資料進行操作,( atomic,synchronized);

可見性:一個線程對主記憶體的修改可以及時地被其他線程看到,(synchronized,volatile);

有序性:一個線程觀察其他執行緒中的指令執行順序,由於指令重排序,該觀察結果一般雜亂無序,(happens-before原則)。

多執行緒鎖的升級原理是什麼?

在Java中,鎖共有4種狀態,等級從低到高依序為:無狀態鎖,偏向鎖,輕量級鎖和重量級鎖狀態,這幾個狀態會隨著競爭狀況逐漸升級。鎖可以升級但不能降級。

鎖定升級的圖示流程: 

#

java的多執行緒常見面試題

什麼是死鎖?

死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。

是作業系統層面的錯誤,是進程死鎖的簡稱,最早在1965 年由Dijkstra 在研究銀行家演算法時提出的,它是電腦作業系統乃至整個並發程式設計領域最難處理的問題之一。

怎麼防止死鎖?

死鎖的四個必要條件:

互斥條件:進程對所指派的資源不允許其他行程進行訪問,若其他行程存取該資源,只能等待,直至佔有該資源的進程使用完成後釋放該資源

請求和保持條件:進程獲得一定的資源之後,又對其他資源發出請求,但是該資源可能被其他進程佔有,此事請求阻塞,但又對自己獲得的資源保持不放

不可剝奪條件:是指進程已獲得的資源,在未完成使用之前,不可被剝奪,只能在使用完後自己釋放

環路等待條件:是指進程發生死鎖後,若干進程之間形成一種頭尾相接的循環等待資源關係

這四個條件是死鎖的必要條件,只要係統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。

了解死鎖的原因,特別是產生死鎖的四個必要條件,就可以最大可能地避免、預防和 解除死鎖。

所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確 定資源的合理分配演算法,避免進程永久佔據系統資源。

此外,也要防止行程在等待狀態的情況下佔用資源。因此,對資源的分配要給予合理的規劃。

ThreadLocal 是什麼?有哪些使用場景?

執行緒局部變數是侷限於執行緒內部的變量,屬於執行緒本身所有,不在多個執行緒間共用。 Java提供ThreadLocal類別來支援線程局部變量,是一種實現線程安全的方式。

但是在管理環境下(如 web 伺服器)使用執行緒局部變數的時候要特別小心,在這種情況下,工作執行緒的生命週期比任何應用變數的生命週期都要長。

任何執行緒局部變數一旦在工作完成後沒有釋放,Java 應用程式就存在記憶體外洩的風險。

說一下 synchronized 底層實作原理?

synchronized可以保證方法或程式碼區塊在運行時,同一時刻只有一個方法可以進入到臨界區,同時它還可以保證共享變數的記憶體可見性。

Java中每個物件都可以當作鎖,這是synchronized實作同步的基礎:

普通同步方法,鎖定是目前實例物件

#靜態同步方法,鎖是目前類別的class物件

同步方法區塊,鎖是括號裡面的物件

synchronized 和volatile 的差別是什麼?

volatile本質是在告訴jvm目前變數在暫存器(工作記憶體)中的值是不確定的,需要從主記憶體讀取;synchronized 則是鎖定目前變量,只有目前執行緒可以訪問該變量,其他線程被阻塞住。

volatile僅能使用在變數層級;synchronized則可以使用在變數、方法、和類別層級的。

volatile僅能實現變數的修改可見性,不能保證原子性;而synchronized則可以保證變數的修改可見性和原子性。

volatile不會造成執行緒的阻塞;synchronized可能會造成執行緒的阻塞。

volatile標記的變數不會被編譯器最佳化;synchronized標記的變數可以被編譯器最佳化。

synchronized 和 Lock 有什麼不同?

首先synchronized是java內建關鍵字,在jvm層面,Lock是個java類別;

synchronized無法判斷是否取得鎖定的狀態,Lock可以判斷是否取得到鎖定;

synchronized會自動釋放鎖定(a 執行緒執行完同步程式碼會釋放鎖定;b 執行緒執行過程中發生異常會釋放鎖定),Lock需在finally中手動釋放鎖定(unlock()方法釋放鎖定),否則容易造成線程死鎖;

用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,則線程2線程等待。如果線程1阻塞,線程2則會一直等待下去,而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了;

synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平(兩者皆可);

Lock鎖適合大量同步的程式碼的同步問題,synchronized鎖適合程式碼少量的同步問題。

synchronized 和 ReentrantLock 差別是什麼?

synchronized是和if、else、for、while一樣的關鍵字,ReentrantLock是類,這是二者的本質差異。

既然ReentrantLock是類,那麼它就提供了比synchronized更多更靈活的特性,可以被繼承、可以有方法、可以有各種各樣的類變量,ReentrantLock比synchronized的擴展性體現在幾點上: 

ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖 

ReentrantLock可以獲取各種鎖的資訊

ReentrantLock可以靈活地實現多路通知 

另外,二者的鎖定機制其實也是不一樣的:ReentrantLock底層呼叫的是Unsafe的park方法加鎖,synchronized操作的應該是物件頭中mark word。

說一下 atomic 的原理?

Atomic套件中的類別基本的特性就是在多執行緒環境下,當有多個執行緒同時對單一(包括基本型別及參考型別)變數進行操作時,具有排他性,即當當多個執行緒同時對該變數的值進行更新時,僅有一個執行緒能成功,而未成功的執行緒可以向自旋鎖一樣,繼續嘗試,一直等到執行成功。

Atomic系列的類別中的核心方法都會呼叫unsafe類別中的幾個本地方法。我們需要先知道一個東西就是Unsafe類,全名為:sun.misc.Unsafe,這個類包含了大量的對C代碼的操作,包括很多直接內存分配以及原子操作的調用,而它之所以標記為非安全的,是告訴你這個裡面大量的方法調用都會存在安全隱患,需要小心使用,否則會導致嚴重的後果,例如在通過unsafe分配內存的時候,如果自己指定某些區域可能會導致一些類似C 一樣的指標越界到其他進程的問題。

以上是java的多執行緒常見面試題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。