更新時間:2020-10-15 17:21:59 來源:動力節點 瀏覽2082次
CPU是電腦的核心所在,如果能提高CPU的運行效率,相應的也能提高一個程序的運行效率。采用多線程的方式就可以提高CPU的使用率,可以同時完成幾件事情而互不干擾,在java語言中,學習好多線程無疑是至關重要的,多線程面試題在java程序員的面試中是常出現的,下面總結了一些常考的最新多線程面試題,大家可以一起來學習。
1、說明類java.lang.ThreadLocal的作用和原理是什么?
答:作用:要編寫一個多線程安全(Thread-safe)的程序是困難的,為了讓線程共享資源,必須小心地對共享資源進行同步,同步帶來一定的效能延遲,而另一方面,在處理同步的時候,又要注意對象的鎖定與釋放,避免產生死結,種種因素都使得編寫多線程程序變得困難。嘗試從另一個角度來思考多線程共享資源的問題,既然共享資源這么困難,那么就干脆不要共享,何不為每個線程創造一個資源的復本。將每一個線程存取數據的行為加以隔離,實現的方法就是給予每個線程一個特定空間來保管該線程所獨享的資源。
ThreadLocal的原理:ThreadLocal做到為每一個線程維護變量的副本,實現的思路很簡單,在ThreadLocal類中有一個Map,用于存儲每一個線程的變量的副本。
2、在java中怎么實現多線程?描述線程狀態的變化過程。
答:當多個線程訪問同一個數據時,容易出現線程安全問題,需要某種方式來確保資源在某一時刻只被一個線程使用。需要讓線程同步,保證數據安全線程同步的實現方案: 同步代碼塊和同步方法,均需要使用synchronized關鍵字。
同步代碼塊:public void makeWithdrawal(int amt) {
synchronized (acct) { }
}
同步方法:public synchronized void makeWithdrawal(int amt) { }
線程同步的好處:解決了線程安全問題;線程同步的缺點:性能下降,可能會帶來死鎖。
3、樂觀鎖與悲觀鎖各是什么?
答:悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似于write_condition機制的其實都是提供的樂觀鎖。
4、在多線程編程里,wait方法的調用方式是怎樣的?
答:wait方法是線程通信的方法之一,必須用在 synchronized方法或者synchronized代碼塊中,否則會拋出異常,這就涉及到一個“鎖”的概念,而wait方法必須使用上鎖的對象來調用,從而持有該對象的鎖進入線程等待狀態,直到使用該上鎖的對象調用notify或者notifyAll方法來喚醒之前進入等待的線程,以釋放持有的鎖。
5、volatile關鍵字是否能保證線程安全?
答:不能。雖然volatile提供了同步的機制,但是知識一種弱的同步機制,如需要強線程安全,還需要使用synchronized。Java語言提供了一種稍弱的同步機制,即volatile變量,用來確保將變量的更新操作通知到其他線程。當把變量聲明為volatile類型后,編譯器與運行時都會注意到這個變量是共享的,因此不會將該變量上的操作與其他內存操作一起重排序。volatile變量不會被緩存在寄存器或者對其他處理器不可見的地方,因此在讀取volatile類型的變量時總會返回最新寫入的值。
6、創建線程的有哪些方式?
答:(1)繼承Thread類創建線程類;(2)通過Runnable接口創建線程類;(3)通過Callable和Future創建線程;(4)通過線程池創建。
7、線程池的優點都有什么?
答:(1)重用存在的線程,減少對象創建銷毀的開銷;(2)可有效的控制最大并發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞;(3)提供定時執行、定期執行、單線程、并發數控制等功能。
8、synchronized和ReentrantLock的區別?
答:synchronized是和if、else、for、while一樣的關鍵字,ReentrantLock是類,這是二者的本質區別。既然ReentrantLock是類,那么它就提供了比synchronized更多更靈活的特性,可以被繼承、可以有方法、可以有各種各樣的類變量,ReentrantLock比synchronized的擴展性體現在幾點上:
(1)ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖;
(2)ReentrantLock可以獲取各種鎖的信息;
(3)ReentrantLock可以靈活地實現多路通知。
9、線程的調度策略都有什么?
答:線程調度器選擇優先級最高的線程運行,但是,如果發生以下情況,就會終止線程的運行:(1)線程體中調用了yield方法讓出了對cpu的占用權利;(2)線程體中調用了sleep方法使線程進入睡眠狀態;(3)線程由于IO操作受到阻塞;(4)另外一個更高優先級線程出現;(5)在支持時間片的系統中,該線程的時間片用完。
10、死鎖的原因?
答:(1)是多個線程涉及到多個鎖,這些鎖存在著交叉,所以可能會導致了一個鎖依賴的閉環。例如:線程在獲得了鎖A并且沒有釋放的情況下去申請鎖B,這時,另一個線程已經獲得了鎖B,在釋放鎖B之前又要先獲得鎖A,因此閉環發生,陷入死鎖循環。
(2)默認的鎖申請操作是阻塞的。
所以要避免死鎖,就要在一遇到多個對象鎖交叉的情況,就要仔細審查這幾個對象的類中的所有方法,是否存在著導致鎖依賴的環路的可能性。總之是盡量避免在一個同步方法中調用其它對象的延時方法和同步方法。
11、怎么喚醒一個阻塞的線程?
答:如果線程是因為調用了wait()、sleep()或者join()方法而導致的阻塞,可以中斷線程,并且通過拋出InterruptedException來喚醒它;如果線程遇到了IO阻塞,無能為力,因為IO是操作系統實現的,Java代碼并沒有辦法直接接觸到操作系統。
12、不可變對象對多線程有什么幫助?
答:不可變對象保證了對象的內存可見性,對不可變對象的讀取不需要進行額外的同步手段,提升了代碼執行效率。
13、什么是多線程的上下文切換?
答:多線程的上下文切換是指CPU控制權由一個已經正在運行的線程切換到另外一個就緒并等待獲取CPU執行權的線程的過程。
14、同步和異步有何異同?
答:(1)如果數據將在線程間共享。例如正在寫的數據以后可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那么這些數據就是共享數據,必須進行同步存取。
(2)當應用程序在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。
15、Java線程數過多會造成什么異常?
答:(1)線程的生命周期開銷非常高;(2)消耗過多的CPU資源。如果可運行的線程數量多于可用處理器的數量,那么有線程將會被閑置。大量空閑的線程會占用許多內存,給垃圾回收器帶來壓力,而且大量的線程在競爭CPU資源時還將產生其他性能的開銷;(3)降低穩定性。JVM在可創建線程的數量上存在一個限制,這個限制值將隨著平臺的不同而不同,并且承受著多個因素制約,包括JVM的啟動參數、Thread構造函數中請求棧的大小,以及底層操作系統對線程的限制等。如果破壞了這些限制,那么可能拋出OutOfMemoryError異常。
以上是今天整理的java多線程面試題的內容,大家可以根據給出相應的參考答案來學習。CPU要花同樣多的時間去完成所有的事情,但多線程可以讓CPU摻插地同時做多件事情,希望朋友們可以通過多線程編程教程來學習更多的java多線程的知識。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習