2021年最詳細Java多執行緒面試問題集錦,看完可以和麵試官扯皮了
當我刷到這條脈脈的時候,想到當年老闆面試我的時候,拿多執行緒問題虐我時,想想當時太難了。 悄悄給大家看幾道阿里必問的面試題,測測能完美地回答幾道呢?
有沒有一種一定能保證執行緒安全的程式碼寫法?(偷偷告訴你,真的有!)
多個執行緒如何保持A1B2C3等順序交替輸出?
synchronized volatile的CPU原理是如何實現的?
無鎖、偏向鎖、輕量級鎖、重量級鎖有什麼差別?
如何正確地啟動和停止一個執行緒?
執行緒和執行緒的區別的是什麼?為什麼纖程比較輕量級?
ThreadLocal有沒有記憶體洩漏的問題?為什麼?
下列三種業務,應該如何使用執行緒池:
高併發、任務執行時間短
前言
怎麼樣是不是感覺很難,而且現在畢業季快到了,不管是實習生還是有想要跳槽的大佬們即將進入找工作的高峰期,在任何Java面試當中多執行緒和併發方面的問題都是必不可少的一部分。
所以這篇文章是我最新整理的最全多執行緒併發面試47題和答案總結,希望對想進BAT的同學有幫助,由於篇幅較長,建議收藏後細看~
這些多執行緒的問題,有些來源於各大網站、有些來源於自己的思考。可能有些問題網上有、可能有些問題對應的答案也有、也可能有些各位網友也都看過,但是本文寫作的重心就是所有的問題都會按照自己的理解回答一遍,不會去看網上的答案,因此可能有些問題講得不對,能指正的希望大家不吝指教。
1、什麼是執行緒安全和執行緒不安全?
通俗地說:加鎖的就是是執行緒安全的,不加鎖的就是是執行緒不安全的
執行緒安全
執行緒安全: 就是多執行緒訪問時,採用了加鎖機制,當一個執行緒訪問該類的某個資料時,進行保護,其他執行緒不能進行訪問,直到該執行緒讀取完,其他執行緒才可使用。不會出現資料不一致或者資料汙染。
一個執行緒安全的計數器類的同一個例項物件在被多個執行緒使用的情況下也不會出現計算失誤。很顯然你可以將集合類分成兩組,執行緒安全和非執行緒安全的。Vector 是用同步方法來實現執行緒安全的, 而和它相似的ArrayList不是執行緒安全的。
執行緒不安全
執行緒不安全:就是不提供資料訪問保護,有可能出現多個執行緒先後更改資料造成所得到的資料是髒資料
如果你的程式碼所在的程序中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。
執行緒安全問題都是由全域性變數及靜態變數引起的。若每個執行緒中對全域性變數、靜態變數只有讀操作,而無寫操作,一般來說,這個全域性變數是執行緒安全的;若有多個執行緒同時執行寫操作,一般都需要考慮執行緒同步,否則的話就可能影響執行緒安全。
2、什麼是自旋鎖?
基本概念
自旋鎖是SMP架構中的一種low-level的同步機制。
當執行緒A想要獲取一把自旋鎖而該鎖又被其它執行緒鎖持有時,執行緒A會在一個迴圈中自旋以檢測鎖是不是已經可用了。
自旋鎖需要注意:
由於自旋時不釋放CPU,因而持有自旋鎖的執行緒應該儘快釋放自旋鎖,否則等待該自旋鎖的執行緒會一直在那裡自旋,這就會浪費CPU時間。
持有自旋鎖的執行緒在sleep之前應該釋放自旋鎖以便其它執行緒可以獲得自旋鎖。
實現自旋鎖
一個簡單的while就可以滿足你的要求。
目前的JVM實現自旋會消耗CPU,如果長時間不呼叫doNotify方法,doWait方法會一直自旋,CPU會消耗太大。
public class MyWaitNotify3{
MonitorObject myMonitorObject = new MonitorObject(); boolean wasSignalled = false; public void doWait(){ synchronized(myMonitorObject){ while(!wasSignalled){ try{
myMonitorObject。wait();
} catch(InterruptedException e){。。。}
} //clear signal and continue running。
wasSignalled = false;
}
} public void doNotify(){ synchronized(myMonitorObject){
wasSignalled = true;
myMonitorObject。notify();
}
}
}
3、併發程式設計三要素?
1)原子性
原子性指的是一個或者多個操作,要麼全部執行並且在執行的過程中不被其他操作打斷,要麼就全部都不執行。
2)可見性
可見性指多個執行緒操作一個共享變數時,其中一個執行緒對變數進行修改後,其他執行緒可以立即看到修改的結果。
3)有序性
有序性,即程式的執行順序按照程式碼的先後順序來執行。
4、實現可見性的方法有哪些?
synchronized或者Lock:保證同一個時刻只有一個執行緒獲取鎖執行程式碼,鎖釋放之前把最新的值重新整理到主記憶體,實現可見性。
5、多執行緒的價值?
1)發揮多核CPU的優勢
多執行緒,可以真正發揮出多核CPU的優勢來,達到充分利用CPU的目的,採用多執行緒的方式去同時完成幾件事情而不互相干擾。
2)防止阻塞
從程式執行效率的角度來看,單核CPU不但不會發揮出多執行緒的優勢,反而會因為在單核CPU上執行多執行緒導致執行緒上下文的切換,而降低程式整體的效率。但是單核CPU我們還是要應用多執行緒,就是為了防止阻塞。試想,如果單核CPU使用單執行緒,那麼只要這個執行緒阻塞了,比方說遠端讀取某個資料吧,對端遲遲未返回又沒有設定超時時間,那麼你的整個程式在資料返回回來之前就停止運行了。多執行緒可以防止這個問題,多條執行緒同時執行,哪怕一條執行緒的程式碼執行讀取資料阻塞,也不會影響其它任務的執行。
3)便於建模
這是另外一個沒有這麼明顯的優點了。假設有一個大的任務A,單執行緒程式設計,那麼就要考慮很多,建立整個程式模型比較麻煩。但是如果把這個大的任務A分解成幾個小任務,任務B、任務C、任務D,分別建立程式模型,並透過多執行緒分別執行這幾個任務,那就簡單很多了。
6、建立執行緒的有哪些方式?
1)繼承Thread類建立執行緒類
2)透過Runnable介面建立執行緒類
3)透過Callable和Future建立執行緒
4)透過執行緒池建立
7、建立執行緒的三種方式的對比?
1)採用實現Runnable、Callable介面的方式建立多執行緒。
優勢是:
執行緒類只是實現了Runnable介面或Callable介面,還可以繼承其他類。
在這種方式下,多個執行緒可以共享同一個target物件,所以非常適合多個相同執行緒來處理同一份資源的情況,從而可以將CPU、程式碼和資料分開,形成清晰的模型,較好地體現了面向物件的思想。
劣勢是:
程式設計稍微複雜,如果要訪問當前執行緒,則必須使用Thread。currentThread()方法。
2)使用繼承Thread類的方式建立多執行緒
優勢是:
編寫簡單,如果需要訪問當前執行緒,則無需使用Thread。currentThread()方法,直接使用this即可獲得當前執行緒。
劣勢是:
執行緒類已經繼承了Thread類,所以不能再繼承其他父類。
3)Runnable和Callable的區別
Callable規定(重寫)的方法是call(),Runnable規定(重寫)的方法是run()。
Callable的任務執行後可返回值,而Runnable的任務是不能返回值的。
Call方法可以丟擲異常,run方法不可以。
執行Callable任務可以拿到一個Future物件,表示非同步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果。透過Future物件可以瞭解任務執行情況,可取消任務的執行,還可獲取執行結果。
8、執行緒的狀態流轉圖
執行緒的生命週期及五種基本狀態:
9、Java執行緒具有五中基本狀態
1)新建狀態(New):當執行緒物件對建立後,即進入了新建狀態,如:Thread t = new MyThread();
2)就緒狀態(Runnable):當呼叫執行緒物件的start()方法(t。start();),執行緒即進入就緒狀態。處於就緒狀態的執行緒,只是說明此執行緒已經做好了準備,隨時等待CPU排程執行,並不是說執行了t。start()此執行緒立即就會執行;
3)執行狀態(Running):當CPU開始排程處於就緒狀態的執行緒時,此時執行緒才得以真正執行,即進入到執行狀態。注:就
緒狀態是進入到執行狀態的唯一入口,也就是說,執行緒要想進入執行狀態執行,首先必須處於就緒狀態中;
4)阻塞狀態(Blocked):處於執行狀態中的執行緒由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,才 有機會再次被CPU呼叫以進入到執行狀態。
根據阻塞產生的原因不同,阻塞狀態又可以分為三種:
a。等待阻塞:執行狀態中的執行緒執行wait()方法,使本執行緒進入到等待阻塞狀態;
b。同步阻塞 – 執行緒在獲取synchronized同步鎖失敗(因為鎖被其它執行緒所佔用),它會進入同步阻塞狀態;
c。其他阻塞 – 透過呼叫執行緒的sleep()或join()或發出了I/O請求時,執行緒會進入到阻塞狀態。當sleep()狀態超時、join()等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入就緒狀態。
5)死亡狀態(Dead):執行緒執行完了或者因異常退出了run()方法,該執行緒結束生命週期。
10、什麼是執行緒池?有哪幾種建立方式?
執行緒池就是提前建立若干個執行緒,如果有任務需要處理,執行緒池裡的執行緒就會處理任務,處理完之後執行緒並不會被銷燬,而是等待下一個任務。由於建立和銷燬執行緒都是消耗系統資源的,所以當你想要頻繁的建立和銷燬執行緒的時候就可以考慮使用執行緒池來提升系統的效能。
java 提供了一個
java。util。concurrent。Executor介面的實現用於建立執行緒池。
11、四種執行緒池的建立:
1)newCachedThreadPool建立一個可快取執行緒池
2)newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數。
3)newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。
4)newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務。
12、執行緒池的優點?
1)重用存在的執行緒,減少物件建立銷燬的開銷。
2)可有效地控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
3)提供定時執行、定期執行、單執行緒、併發數控制等功能。
由於篇幅不允許,所以下面只顯示題目,然後需要多執行緒面試問題集錦(含答案)的文件可以點這裡自行下載
13、常用的併發工具類有哪些?
14、CyclicBarrier和CountDownLatch的區別
15、synchronized的作用?
16、volatile關鍵字的作用
17、什麼是CAS
18、CAS的問題
19、什麼是Future?
20、什麼是AQS
21、AQS支援兩種同步方式:
22、ReadWriteLock是什麼
23、FutureTask是什麼
24、synchronized和ReentrantLock的區別
25、什麼是樂觀鎖和悲觀鎖
26、執行緒B怎麼知道執行緒A修改了變數
27、synchronized、volatile、CAS比較
28、sleep方法和wait方法有什麼區別?
29、ThreadLocal是什麼?有什麼用?
30、為什麼wait()方法和notify()/notifyAll()方法要在同步塊中被呼叫
31、多執行緒同步有哪幾種方法?
32、執行緒的排程策略
33、ConcurrentHashMap的併發度是什麼
34、Linux環境下如何查詢哪個執行緒使用CPU最長
35、Java死鎖以及如何避免?
36、死鎖的原因
37、怎麼喚醒一個阻塞的執行緒
38、不可變物件對多執行緒有什麼幫助
39、什麼是多執行緒的上下文切換
40、如果你提交任務時,執行緒池佇列已滿,這時會發生什麼
41、Java中用到的執行緒排程演算法是什麼
42、什麼是執行緒排程器(Thread Scheduler)和時間分片(Time Slicing)?
43、什麼是自旋
44、Java
45、單例模式的執行緒安全性
46、Semaphore有什麼作用
47、Executors類是什麼?
48、執行緒類的構造方法、靜態塊是被哪個執行緒呼叫的
49、同步方法和同步塊,哪個是更好的選擇?
50、Java執行緒數過多會造成什麼異常?
文中所有面試內容已經整理在網盤,如有需要可以私信我傳送 666 即可領取
相關文章
- 2021-09-21為什麼同樣是手機,蘋果卻比安卓的更順暢耐用?
- 2021-06-13使用電腦時,提示電腦記憶體不足,怎樣才能進行深度記憶體清理
- 2021-06-052021年最新CPU單核效能排行天梯圖(高畫質,包括M1)
- 2021-05-2716GB+512GB,釋出不到一年下跌800元,頂配5G旗艦無奈少人問津
- 2021-04-27高原環境執行的電機,效能要求有哪些特殊性?