首頁 > 軟體

(小奇JAVA面試)每日10道Java面試題打卡—Java基礎篇3

2021-05-27 02:01:30
文章配圖

二十一、說說你對執行緒安全的理解

與其說是執行緒安全,不如說是記憶體安全,堆是共享記憶體,可以被所有執行緒訪問。

是程序和執行緒共有的空間,每一個程序裡面有多個執行緒,分全局堆和局部堆,全局堆就是所有沒有分配的空間,局部堆就是分配給使用者的空間,堆在作業系統對程序初始化的時候分配,運行過程中也可以向系統要額外的堆,但是用完了還要還給作業系統,要不然就是記憶體洩漏。

是每個執行緒獨有的,所以棧是執行緒安全的,每個執行緒的棧互相獨立。

目前主流的作業系統都是多工的,即多個程序同事運行,為了保證安全,每個程序只能訪問分配給自己的記憶體空間,而不能訪問別的程序的,這是由作業系統保障的。

在每個程序的記憶體空間中都會有一塊特殊的公共區域,通常稱為堆(記憶體),程序內的所有執行緒都可以訪問這個區域,所以這個區域是執行緒不安全的。

二十二、Thread和Runable的區別

Thread和Runnable的實質是繼承關係,沒有可比性,無論使用Runnable還是Thread,都會new Thread,然後執行run()方法,用法上,如果有複雜的執行緒操作需求,那就選擇繼承Thread,如果只是簡單的執行一個任務,那就實現runnable。

二十三、說說你對守護執行緒的理解

守護執行緒:為所有非守護執行緒提供服務的執行緒,任何一個守護執行緒都是在整個JVM中所有非守護執行緒的保姆。

守護執行緒類似於整個程序的一個小兵,它的生死無關重要,但是它卻依賴整個進行而運行,如果其他執行緒結束了,沒有要執行的了,程式就結束了,守護執行緒立馬就中斷了。

注意:由於守護執行緒的終止是自身無法控制的,因此不要把IO、File等重要操作邏輯分配給它,因為它不靠譜。

二十四、ThreadLocal的原理的使用場景

每一個Thread物件均含有一個ThreadLocalMap類型的成員變數threadLocal,它儲存本執行緒中所有ThreadLocal物件及其對應的值。

當執行set方法時,ThreadLocal首先會獲取當前執行緒物件,然後獲取當前執行緒的ThreadLocalMap物件,再以當前ThreadLocal物件為key,將值儲存進ThreadLocalMap物件中。

get方法執行過程類似,ThreadLocal首先會獲取當前執行緒物件,然後獲取當前執行緒的ThreadLocalMap物件,再以當前ThreadLocal物件為key,獲取對應的value。

使用場景:

1、在進行物件跨層傳遞的時候,使用ThreadLocal可以避免多次傳遞,打破層次間的約束。

2、執行緒間資料隔離。

3、進行實物操作,用於儲存執行緒事務資訊。

4、資料庫連線,Session會話管理。

二十五、ThreadLocal記憶體洩漏原因,如何避免

記憶體洩漏為程式在申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩漏危害可以忽略,但記憶體洩漏堆積後果很嚴重。

不再會被使用的物件或者變數佔用的記憶體不能被回收,就是記憶體洩漏。

強引用:使用最普通的引用 new,一個物件具有強引用,不會被垃圾回收器回收,當記憶體空間不足,java虛擬機器寧願拋出outOfMemoryError錯誤,使程式異常終止,也不回收這種物件。

如果想取消強引用和某個物件之間的關聯,可以顯式地將引用複製為null,這樣可以使JVM在合適的時間就會回收該物件。

弱引用:jvm進行垃圾回收時,無論記憶體是否充足,都會回收被弱引用關聯的物件,在java中,用java.lang.ref.WeakReference類來表示,可以在快取中使用弱引用。

ThreadLocal的實現原理,每一個Thread維護了一個ThreadLocalMap,key為使用弱引用的ThreadLocal例項,value為執行緒變數的副本。

ThreadLocal正確的使用方法:

每次使用完ThreadLocal都呼叫它的remove()方法清除資料。

二十六、併發、並行、序列的區別

序列在時間上不可能發生重疊,前一個任務沒搞定,下一個任務就只能等著。

並行在時間上是重疊的,兩個任務在同一時刻互不干擾的同時執行。

併發允許兩個任務彼此干擾,統一時間點,只有一個任務運行,交替執行。

二十七、併發的三大特性

1、原子性

原子性是指在一個操作中cpu不可以在中途暫停然後再排程,即不被中斷操作,要不全部執行完成,要不都不執行,就好比轉賬,從賬戶A向賬戶B轉1000元,那麼必然包括2個操作:從賬戶A減去1000元,往賬戶B加上1000元。2個操作必須全部完成。

2、可見性

當多個執行緒訪問同一個變數時,一個執行緒修改了這個變數的值,其他執行緒可以立刻看到這個新變化的值。

3、有序性

虛擬機器在進行程式碼編譯時,對於那些改變順序之後不會對最終結果造成影響的程式碼,虛擬機器不一定會按照我們寫的程式碼順序來執行,有可能將他們重排序,實際上,對於有些程式碼進行重排序之後,雖然對變數的值沒有造成影響,但有可能會出現執行緒安全問題。

二十八、為什麼要用執行緒池?解釋下執行緒池參數

1、降低資源消耗:提高執行緒利用率,降低創建和銷燬執行緒的消耗。

2、提高響應速度:任務來了,直接有現成可用可執行,而不是先創建執行緒,再執行。

3、提高執行緒的可管理性:執行緒是稀缺資源,使用執行緒池可以統一分配調優監控。

1》 corePoolSize代表核心執行緒數,也就是正常情況下創建工作的執行緒數,這些執行緒創建後並不會消除,而是一種常駐執行緒。

2》maxinumPoolSize代表最大執行緒數,它與核心執行緒數相對應,表示最大允許被創建的執行緒數,比如當前任務比較多,將核心執行緒數都用完了,還無法滿足需求時,此時就會創建新的執行緒,但是執行緒池內執行緒總數不會超過最大執行緒數。

3》keepAliveTime、unit表示超出核心執行緒數之外的執行緒的空閒存活時間,也就是核心執行緒不會消除,但是超過核心執行緒數的部分執行緒如果空閒一定的時間則會被消除,我們可以通過setkeepAliveTime來設定空閒時間。

4》workQueue用來存放待執行的任務,假設我們現在核心執行緒都已被使用,還有任務進來則全部放入佇列,直到整個佇列被放滿但任務還在持續進入則會開始創建新的執行緒。

5》ThreadFactory實際上是一個執行緒工廠,用來生產執行緒執行任務。

6》Handler:任務拒絕策略,當達到最大執行緒數,執行緒池已經沒有能力繼續處理新提交的任務時,就執行任務拒絕策略。

二十九、簡述執行緒池處理流程

文章配圖

三十、執行緒池中阻塞佇列的作用?為什麼是先新增佇列而不是先創建最大執行緒

1、一般的佇列只能保證作為一個有限長度的緩衝區,如果超出了緩衝長度,就無法保留當前的任務了,阻塞佇列通過阻塞可以保留住當前想要繼續入隊的任務。

2、阻塞佇列可以保證任務佇列中沒有任務時阻塞獲取任務的執行緒,使得執行緒進入wait狀態,釋放cpu資源。

3、阻塞佇列自帶阻塞和喚醒的功能,不需要額外處理,無任務執行時,執行緒池利用阻塞佇列的take方法掛起,從而維持核心執行緒的存活,不至於一直佔用cpu的資源。

4、在創建新執行緒的時候,要獲取全局鎖的,這個時候其它的就得阻塞,影響了整體效率,所以說執行緒的創建是比較消耗資源的。


IT145.com E-mail:sddin#qq.com