2019年Java面試題(五) 線程 2019-04-27

1. 線程同步以及線程調(diào)度相關的方法

- wait():使一個線程處于等待(阻塞)狀態(tài),并且釋放所持有的對象的鎖;

- sleep():使一個正在運行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要處理InterruptedException異常;

- notify():喚醒一個處于等待狀態(tài)的線程,當然在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且與優(yōu)先級無關;

- notityAll():喚醒所有處于等待狀態(tài)的線程,該方法并不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進入就緒狀態(tài);

2. 進程和線程的區(qū)別

進程是執(zhí)行著的應用程序,而線程是進程內(nèi)部的一個執(zhí)行序列。一個進程可以有多個線程。

另一種回答:

線程是進程的一個單元,也是進程內(nèi)的可調(diào)度實體。區(qū)別就是:1、進程內(nèi)的線程共享地址空間,進程則自己獨立的地址空間。2、進程是資源分配和擁有的單位,同一個進程內(nèi)的線程共享進程資源。3、線程是處理器調(diào)度的基本單位。4、兩者均可并發(fā)執(zhí)行。

3. 實現(xiàn)線程有哪幾種方式?啟動線程調(diào)用什么方法?

Java中實現(xiàn)線程有兩種方式:第一種是繼承Thread,第二種是實現(xiàn)Runnable接口。啟動線程用start()方法。

4. 請說出你所知道的線程同步的方法。

wait():使一個線程處于等待狀態(tài),并且釋放所持有的對象的lock。

sleep():使一個正在運行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常。

notify():喚醒一個處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且不是按優(yōu)先級。

notityAll():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。

5. sleep() 和wait() 有什么區(qū)別?

sleep是線程類(Thread)的方法,導致此線程暫停執(zhí)行指定時間,把執(zhí)行機會給其他線程,但是監(jiān)控狀態(tài)依然保持,到時后會自動恢復。調(diào)用sleep不會釋放對象鎖。

? ? wait是Object類的方法,對此對象調(diào)用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態(tài)。

6. 創(chuàng)建線程有幾種方式

創(chuàng)建線程有以下幾種方式:

? 繼承Thread類

? 實現(xiàn)Runnable接口

? 應用程序可以使用Executor框架來創(chuàng)建線程池

實現(xiàn)Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類。在已經(jīng)繼承了別的類的情況下,這需要多繼承(而Java不支持多繼承),只能實現(xiàn)接口。同時,線程池也是非常高效的,很容易實現(xiàn)和使用。

7. synchronized關鍵字的用法,優(yōu)缺點

  答:java關鍵字,當它用來修飾一個方法或者代碼塊的時候,能夠保證在同一時刻最多只有一個線程執(zhí)行該代碼段的代碼;

    synchronized修飾的方法或者對象,只能以同步的方式執(zhí)行,會引起性能問題;無法中斷一個正在等候獲得鎖的線程,也無法通過投票獲得鎖;一個優(yōu)先級高的線程等待一個優(yōu)先級低的線程釋放鎖會導致優(yōu)先級倒置,引起性能風險;

8. Thread 類中的start() 和 run() 方法有什么區(qū)別?

start()方法被用來啟動新創(chuàng)建的線程,而且start()內(nèi)部 調(diào)用了run()方法,這和直接調(diào)用run()方法的效果不一樣。當你調(diào)用run()方法的時候,只會是在原來的線程中調(diào)用,沒有新的線程啟 動,start()方法才會啟動新線程。

9. Java中的volatile 變量是什么?

volatile是一個特殊的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile變量可以保證下一個讀取操作會在前一個寫操作之后發(fā)生,就是上一題的volatile變量規(guī)則。

10. Java中notify 和 notifyAll有什么區(qū)別?

這又是一個刁鉆的問題,因為多線程可以等待單監(jiān)控鎖,Java API 的設計人員提供了一些方法當?shù)却龡l件改變的時候通知它們,但是這些方法沒有完全實現(xiàn)。notify()方法不能喚醒某個具體的線程,所以只有一個線程在等 待的時候它才有用武之地。而notifyAll()喚醒所有線程并允許他們爭奪鎖確保了至少有一個線程能繼續(xù)運行。

11. 為什么wait, notify 和 notifyAll這些方法不在thread類里面?

JAVA提供的鎖是對象級的而不是線程級的,每個對象都有鎖,通 過線程獲得。如果線程需要等待某些鎖那么調(diào)用對象中的wait()方法就有意義了。如果wait()方法定義在Thread類中,線程正在等待的是哪個鎖 就不明顯了。簡單的說,

由于wait,notify和notifyAll都是鎖級別的操作,所以把他們定義在Object類中因為鎖屬于對象。

12. 為什么wait和notify方法要在同步塊中調(diào)用?

主要是因為Java API強制要求這樣做,如果你不這么做,你的代碼會拋出IllegalMonitorStateException異常。還有一個原因是為了避免wait和notify之間產(chǎn)生競態(tài)條件。

13. Java中的同步集合與并發(fā)集合有什么區(qū)別?

同步集合與并發(fā)集合都為多線程和并發(fā)提供了合適的線程安全的集合,不過并發(fā)集合的可擴展性更高。在Java1.5之前程序員們只有同步集合來用且在 多線程并發(fā)的時候會導致爭用,阻礙了系統(tǒng)的擴展性。Java5介紹了并發(fā)集合像ConcurrentHashMap,不僅提供線程安全還用鎖分離和內(nèi)部分 區(qū)等現(xiàn)代技術提高了可擴展性。

14. Java中堆和棧有什么不同?

棧是一種線形集合,其添加和刪除元素的操作應在同一段完成。棧按照后進先出的方式進行處理。

堆是棧的一個組成元素

15. 什么是線程池? 為什么要使用它?

創(chuàng)建線程要花費昂貴的資源和時間,如果任務來了才創(chuàng)建線程那么響應時間會變長,而且一個進程能創(chuàng)建的線程數(shù)有限。為了避免這些問題,在程序啟動的時 候就創(chuàng)建若干線程來響應處理,它們被稱為線程池,里面的線程叫工作線程。從JDK1.5開始,Java API提供了Executor框架讓你可以創(chuàng)建不同的線程池。比如單線程池,每次處理一個任務;數(shù)目固定的線程池或者是緩存線程池(一個適合很多生存期短 的任務的程序的可擴展線程池)。

16. Java多線程中調(diào)用wait() 和 sleep()方法有什么不同?

Java程序中wait 和 sleep都會造成某種形式的暫停,它們可以滿足不同的需要。wait()方法用于線程間通信,如果等待條件為真且其它線程被喚醒時它會釋放鎖,而 sleep()方法僅僅釋放CPU資源或者讓當前線程停止執(zhí)行一段時間,但不會釋放鎖。

17. 同步方法和同步代碼塊的區(qū)別是什么?

同步方法就是在方法前加關鍵字synchronized,然后被同步的方法一次只能有一個線程進入,其他線程等待。

而同步代碼塊則是在方法內(nèi)部使用大括號使得一個代碼塊得到同步。同步塊會有一個鎖定的“對象”。同步代碼塊的同步范圍更加準確。

18. 同步和異步有何異同,在什么情況下分別使用他們?舉例說明。

如果數(shù)據(jù)將在線程間共享。例如正在寫的數(shù)據(jù)以后可能被另一個線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進行同步存取。

當應用程序在對象上調(diào)用了一個需要花費很長時間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。

19. 什么是Java優(yōu)先級隊列(Priority Queue)?

PriorityQueue是一個基于優(yōu)先級堆的無界隊列,它的元素是按照自然順序(natural order)排序的。在創(chuàng)建的時候,我們可以給它提供一個負責給元素排序的比較器。PriorityQueue不允許null值,因為他們沒有自然順序,或者說他們沒有任何的相關聯(lián)的比較器。最后,PriorityQueue不是線程安全的,入隊和出隊的時間復雜度是O(log(n))。

20. 什么是同步?

同步用來控制共享資源在多個線程間的訪問,以保證同一時間內(nèi)只有一個線程能訪問到這個資源。在非同步保護的多線程程序里面,一個線程正在修改一個共享變量的時候,可能有另一個線程也在使用或者更新它的值。同步避免了臟數(shù)據(jù)的產(chǎn)生。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容