Java多線程面試題(一)

Java多線程面試題(一)

1.wait方法和sleep方法有什麼不同?

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

2.Java中的ReadWriteLock是什麼?

一般而言,讀寫鎖是用來提升併發程序性能的鎖分離技術的成果。Java中的ReadWriteLock是Java 5 中新增的一個接口,一個ReadWriteLock維護一對關聯的鎖,一個用於只讀操作一個用於寫。在沒有寫線程的情況下一個讀鎖可能會同時被多個讀線程持有。寫鎖是獨佔的,你可以使用JDK中的ReentrantReadWriteLock來實現這個規則,它最多支持65535個寫鎖和65535個讀鎖。

3.Java線程池中submit() 和 execute()方法有什麼區別?

兩個方法都可以向線程池提交任務,execute()方法的返回類型是void,它定義在Executor接口中, 而submit()方法可以返回持有計算結果的Future對象,它定義在ExecutorService接口中,它擴展了Executor接口,其它線程池類像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有這些方法。

4.什麼是不可變對象,它對寫併發應用有什麼幫助?

immutable Objects(不可變對象)就是那些一旦被創建,它們的狀態就不能被改變的Objects,每次對他們的改變都是產生了新的immutable的對象,而mutable Objects(可變對象)就是那些創建後,狀態可以被改變的Objects.

如何在Java中寫出Immutable的類?
1. immutable對象的狀態在創建之後就不能發生改變,任何對它的改變都應該產生一個新的對象。
2. immutable類的所有的屬性都應該是final的。
3. 對象必須被正確的創建,比如:對象引用在對象創建過程中不能泄露(leak)。
4. 對象應該是final的,以此來限制子類繼承父類,以避免子類改變了父類的immutable特性。
5. 如果類中包含mutable類對象,那麼返回給客戶端的時候,返回該對象的一個拷貝,而不是該對象本身(該條可以歸爲第一條中的一個特例)

使用Immutable類的好處:
1. Immutable對象是線程安全的,可以不用被synchronize就在併發環境中共享
2.Immutable對象簡化了程序開發,因爲它無需使用額外的鎖機制就可以在線程間共享
3. Immutable對象提高了程序的性能,因爲它減少了synchroinzed的使用
4. Immutable對象是可以被重複使用的,你可以將它們緩存起來重複使用,就像字符串字面量和整型數字一樣。你可以使用靜態工廠方法來提供類似於valueOf()這樣的方法,它可以從緩存中返回一個已經存在的Immutable對象,而不是重新創建一個。

5.Thread類中的yield方法有什麼作用?

Yield方法可以暫停當前正在執行的線程對象,讓其它有相同優先級的線程執行。它是一個靜態方法而且只保證當前線程放棄CPU佔用而不能保證使其它線程一定能佔用CPU,執行yield()的線程有可能在進入到暫停狀態後馬上又被執行。

6.Thread 類中的start() 和 run() 方法有什麼區別?

start()方法被用來啓動新創建的線程,而且start()內部調用了run()方法,這和直接調用run()方法的效果不一樣。當你調用run()方法的時候,只會是在原來的線程中調用,沒有新的線程啓動,start()方法纔會啓動新線程。

7.一個線程運行時發生異常會怎樣?

簡單的說,如果異常沒有被捕獲該線程將會停止執行。Thread.UncaughtExceptionHandler是用於處理未捕獲異常造成線程突然中斷情況的一個內嵌接口。當一個未捕獲異常將造成線程中斷的時候JVM會使用Thread.getUncaughtExceptionHandler()來查詢線程的UncaughtExceptionHandler並將線程和異常作爲參數傳遞給handler的uncaughtException()方法進行處理。查看詳情。

8.什麼是ThreadLocal?

ThreadLocal是Java裏一種特殊的變量。每個線程都有一個ThreadLocal就是每個線程都擁有了自己獨立的一個變量,競爭條件被徹底消除了。它是爲創建代價高昂的對象獲取線程安全的好方法,比如你可以用ThreadLocal讓SimpleDateFormat變成線程安全的,因爲那個類創建代價高昂且每次調用都需要創建不同的實例所以不值得在局部範圍使用它,如果爲每個線程提供一個自己獨有的變量拷貝,將大大提高效率。首先,通過複用減少了代價高昂的對象的創建個數。其次,你在沒有使用高代價的同步或者不變性的情況下獲得了線程安全。線程局部變量的另一個不錯的例子是ThreadLocalRandom類,它在多線程環境中減少了創建代價高昂的Random對象的個數。

9.怎麼檢測一個線程是否擁有鎖?

在java.lang.Thread中有一個方法叫holdsLock(),它返回true如果當且僅當當前線程擁有某個具體對象的鎖。

10.volatile工作原理?

如果對聲明瞭volatile的變量進行寫操作,JVM就會向處理器發送一條Lock前綴的指令,該Lock指令會使這個變量所在緩存行的數據回寫到系統內存,根據緩存一致性協議,每個處理器都會通過嗅探在總線上傳輸的數據來檢查自己緩存的值是否已過期,當處理器發現自己的緩存行對應的地址被修改,就會將當前處理器的緩存行設置成無效狀態,在下次訪問相同內存地址時,強制執行緩存行填充。查看詳情。

11.Java中synchronized 和 ReentrantLock 有什麼不同?

Java在過去很長一段時間只能通過synchronized關鍵字來實現互斥,它有一些缺點。比如你不能擴展鎖之外的方法或者塊邊界,嘗試獲取鎖時不能中途取消等。Java 5 通過Lock接口提供了更復雜的控制來解決這些問題。 ReentrantLock 類實現了 Lock,它擁有與 synchronized 相同的併發性和內存語義且它還具有可擴展性。查看詳情。

12.有三個線程T1,T2,T3,怎麼確保它們按順序執行?

在多線程中有多種方法讓線程按特定順序執行,你可以用線程類的join()方法在一個線程中啓動另一個線程,另外一個線程完成該線程繼續執行。爲了確保三個線程的順序你應該先啓動最後一個(T3調用T2,T2調用T1),這樣T1就會先完成而T3最後完成。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章