標籤:學習 sso 線程池 列表 proc eval 配置 cte java開發
接上篇Java線程(二),終於寫完了。。。。。。
31) JVM中哪個參數是用來控制線程的棧堆棧小的
這個問題很簡單, -Xss參數用來控制線程的堆棧大小。你可以查看JVM配置列表來瞭解這個參數的更多資訊。
32) Java中synchronized 和 ReentrantLock 有什麼不同?
Java在過去很長一段時間只能通過synchronized關鍵字來實現互斥,它有一些缺點。比如你不能擴充鎖之外的方法或者塊邊界,嘗試擷取鎖時不能中途取消等。Java 5 通過Lock介面提供了更複雜的控制來解決這些問題。 ReentrantLock 類實現了 Lock,它擁有與 synchronized 相同的並發性和記憶體語義且它還具有可擴充性。你可以查看這篇文章瞭解更多
33) 有三個線程T1,T2,T3,怎麼確保它們按順序執行?
在多線程中有多種方法讓線程按特定順序執行,你可以用線程類的join()方法在一個線程中啟動另一個線程,另外一個線程完成該線程繼續執行。為了確保三個線程的順序你應該先啟動最後一個(T3調用T2,T2調用T1),這樣T1就會先完成而T3最後完成。你可以查看這篇文章瞭解更多。
34) Thread類中的yield方法有什麼作用?
Yield方法可以暫停當前正在執行的線程對象,讓其它有相同優先順序的線程執行。它是一個靜態方法而且只保證當前線程放棄CPU佔用而不能保證使其它線程一定能佔用CPU,執行yield()的線程有可能在進入到暫停狀態後馬上又被執行。點擊這裡查看更多yield方法的相關內容。
35) Java中ConcurrentHashMap的並發度是什麼?
ConcurrentHashMap把實際map劃分成若干部分來實現它的可擴充性和安全執行緒。這種劃分是使用並發度獲得的,它是ConcurrentHashMap類建構函式的一個選擇性參數,預設值為16,這樣在多線程情況下就能避免爭用。欲瞭解更多並發度和內部大小調整請閱讀我的文章How ConcurrentHashMap works in Java。
36) Java中Semaphore是什麼?
Java中的Semaphore是一種新的同步類,它是一個計數訊號。從概念上講,從概念上講,訊號量維護了一個許可集合。如有必要,在許可可用前會阻塞每一個 acquire(),然後再擷取該許可。每個 release()添加一個許可,從而可能釋放一個正在阻塞的擷取者。但是,不使用實際的許可對象,Semaphore只對可用許可的號碼進行計數,並採取相應的行動。訊號量常常用於多線程的代碼中,比如資料庫連接池。更多詳細資料請點擊這裡。
37)如果你提交任務時,線程池隊列已滿。會時發會生什麼?
這個問題問得很狡猾,許多程式員會認為該任務會阻塞直到線程池隊列有空位。事實上如果一個任務不能被調度執行那麼ThreadPoolExecutor’s submit()方法將會拋出一個RejectedExecutionException異常。
38) Java線程池中submit() 和 execute()方法有什麼區別?
兩個方法都可以向線程池提交任務,execute()方法的傳回型別是void,它定義在Executor介面中, 而submit()方法可以返回持有計算結果的Future對象,它定義在ExecutorService介面中,它擴充了Executor介面,其它線程池類像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有這些方法。更多詳細資料請點擊這裡。
39) 什麼是阻塞式方法?
阻塞式方法是指程式會一直等待該方法完成期間不做其他事情,ServerSocket的accept()方法就是一直等待用戶端串連。這裡的阻塞是指調用結果返回之前,當前線程會被掛起,直到得到結果之後才會返回。此外,還有非同步和非阻塞式方法在任務完成前就返回。更多詳細資料請點擊這裡。
40) Swing是安全執行緒的嗎? 為什麼?
你可以很肯定的給出回答,Swing不是安全執行緒的,但是你應該解釋這麼回答的原因即便面試官沒有問你為什麼。當我們說swing不是安全執行緒的常常提到它的組件,這些組件不能在多線程中進行修改,所有對GUI組件的更新都要在AWT線程中完成,而Swing提供了同步和非同步兩種回調方法來進行更新。點擊這裡查看更多swing和安全執行緒的相關內容。
41) Java中invokeAndWait 和 invokeLater有什麼區別?
這兩個方法是Swing API 提供給Java開發人員用來從當前線程而不是事件派發線程更新GUI組件用的。InvokeAndWait()同步更新GUI組件,比如一個進度條,一旦進度更新了,進度條也要做出相應改變。如果進度被多個線程跟蹤,那麼就調用invokeAndWait()方法請求事件派發線程對組件進行相應更新。而invokeLater()方法是非同步呼叫更新群組件的。更多詳細資料請點擊這裡。
42) Swing API中那些方法是安全執行緒的?
這個問題又提到了swing和安全執行緒,雖然組件不是安全執行緒的但是有一些方法是可以被多安全執行緒調用的,比如repaint(), revalidate()。 JTextComponent的setText()方法和JTextArea的insert() 和 append() 方法也是安全執行緒的。
43) 如何在Java中建立Immutable對象?
這個問題看起來和多線程沒什麼關係, 但不變性有助於簡化已經很複雜的並發程式。Immutable對象可以在沒有同步的情況下共用,降低了對該對象進行並發訪問時的同步化開銷。可是Java沒有@Immutable這個註解符,要建立不可變類,要實現下面幾個步驟:通過構造方法初始化所有成員、對變數不要提供setter方法、將所有的成員聲明為私人的,這樣就不允許直接存取這些成員、在getter方法中,不要直接返回對象本身,而是複製對象,並返回對象的拷貝。我的文章how to make an object Immutable in Java有詳細的教程,看完你可以充滿自信。
44) Java中的ReadWriteLock是什麼?
一般而言,讀寫鎖是用來提升並發程式效能的鎖分離技術的成果。Java中的ReadWriteLock是Java 5 中新增的一個介面,一個ReadWriteLock維護一對關聯的鎖,一個用於唯讀操作一個用於寫。在沒有寫線程的情況下一個讀鎖可能會同時被多個讀線程持有。寫鎖是獨佔的,你可以使用JDK中的ReentrantReadWriteLock來實現這個規則,它最多支援65535個寫鎖和65535個讀鎖。
45) 多線程中的忙迴圈是什麼?
忙迴圈就是程式員用迴圈讓一個線程等待,不像傳統方法wait(), sleep() 或 yield() 它們都放棄了CPU控制,而忙迴圈不會放棄CPU,它就是在運行一個空迴圈。這麼做的目的是為了保留CPU緩衝,在多核系統中,一個等待線程醒來的時候可能會在另一個核心運行,這樣會重建緩衝。為了避免重建緩衝和減少等待重建的時間就可以使用它了。你可以查看這篇文章獲得更多資訊。
46)volatile 變數和 atomic 變數有什麼不同?
這是個有趣的問題。首先,volatile 變數和 atomic 變數看起來很像,但功能卻不一樣。Volatile變數可以確保先行關係,即寫操作會發生在後續的讀操作之前, 但它並不能保證原子性。例如用volatile修飾count變數那麼 count++ 操作就不是原子性的。而AtomicInteger類提供的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進行增量操作把當前值加一,其它資料類型和引用變數也可以進行相似操作。
47) 如果同步塊內的線程拋出異常會發生什麼?
這個問題坑了很多Java程式員,若你能想到鎖是否釋放這條線索來回答還有點希望答對。無論你的同步塊是正常還是異常退出的,裡面的線程都會釋放鎖,所以對比鎖介面我更喜歡同步塊,因為它不用我花費精力去釋放鎖,該功能可以在finally block裡釋放鎖實現。
48) 單例模式的雙檢鎖是什麼?
這個問題在Java面試中經常被問到,但是面試官對回答此問題的滿意度僅為50%。一半的人寫不出雙檢鎖還有一半的人說不出它的隱患和Java1.5是如何對它修正的。它其實是一個用來建立安全執行緒的單例的老方法,當單例執行個體第一次被建立時它試圖用單個鎖進行效能最佳化,但是由於太過於複雜在JDK1.4中它是失敗的,我個人也不喜歡它。無論如何,即便你也不喜歡它但是還是要瞭解一下,因為它經常被問到。你可以查看how double checked locking on Singleton works這篇文章獲得更多資訊。
49) 如何在Java中建立安全執行緒的Singleton?
這是上面那個問題的後續,如果你不喜歡雙檢鎖而面試官問了建立Singleton類的替代方法,你可以利用JVM的類載入和靜態變數初始化特徵來建立Singleton執行個體,或者是利用枚舉類型來建立Singleton,我很喜歡用這種方法。你可以查看這篇文章獲得更多資訊。
50) 寫出3條你遵循的多線程最佳實務
這種問題我最喜歡了,我相信你在寫並發代碼來提升效能的時候也會遵循某些最佳實務。以下三條最佳實務我覺得大多數Java程式員都應該遵循:
給你的線程起個有意義的名字。
這樣可以方便找bug或追蹤。OrderProcessor, QuoteProcessor or TradeProcessor 這種名字比 Thread-1. Thread-2 and Thread-3 好多了,給線程起一個和它要完成的任務相關的名字,所有的主要架構甚至JDK都遵循這個最佳實務。
避免鎖定和縮小同步的範圍
鎖花費的代價高昂且環境切換更耗費時間空間,試試最低限度的使用同步和鎖,縮小臨界區。因此相對於同步方法我更喜歡同步塊,它給我擁有對鎖的絕對控制權。
多用同步類少用wait 和 notify
首先,CountDownLatch, Semaphore, CyclicBarrier 和 Exchanger 這些同步類簡化了編碼操作,而用wait和notify很難實現對複雜控制流程的控制。其次,這些類是由最好的企業編寫和維護在後續的JDK中它們還會不斷最佳化和完善,使用這些更高等級的同步工具你的程式可以不費吹灰之力獲得最佳化。
多用並發集合少用同步集合
這是另外一個容易遵循且受益巨大的最佳實務,並發集合比同步集合的可擴充性更好,所以在並發編程時使用並發集合效果更好。如果下一次你需要用到map,你應該首先想到用ConcurrentHashMap。我的文章Java並發集合有更詳細的說明。
51) 如何強制啟動一個線程?
這個問題就像是如何強制進行Java記憶體回收,目前還沒有覺得方法,雖然你可以使用System.gc()來進行記憶體回收,但是不保證能成功。在Java裡面沒有辦法強制啟動一個線程,它是被線程調度器控制著且Java沒有公布相關的API。
52) Java中的fork join架構是什麼?
fork join架構是JDK7中出現的一款高效的工具,Java開發人員可以通過它充分利用現代伺服器上的多處理器。它是專門為了那些可以遞迴劃分成許多子模組設計的,目的是將所有可用的處理能力用來提升程式的效能。fork join架構一個巨大的優勢是它使用了工作竊取演算法,可以完成更多任務的背景工作執行緒可以從其它線程中竊取任務來執行。你可以查看這篇文章獲得更多資訊。
53) Java多線程中調用wait() 和 sleep()方法有什麼不同?
Java程式中wait 和 sleep都會造成某種形式的暫停,它們可以滿足不同的需要。wait()方法用於線程間通訊,如果等待條件為真且其它線程被喚醒時它會釋放鎖,而sleep()方法僅僅釋放CPU資源或者讓當前線程停止執行一段時間,但不會釋放鎖。你可以查看這篇文章獲得更多資訊。
一點點熱門Java多線程和並發麵試題,沒有分享所有題的答案但給未來的閱讀者提供了足夠的提示和線索來尋找答案。這文章不僅可以用來準備面試,還能檢查你對多線程、並發、設計模式和競態條件、死結和安全執行緒等線程問題的理解。如果你真的找不到某題的答案,不懂的朋友可以加我Q,或者加群號來一起學習,大家一起學習編程分享視頻,希望能協助喜歡JAVA的朋友。有需要協助的也可以聯絡我。
Java線程(三)