Java面試題——隨機題(一),看看哪些你會哪些你不會
博客說明
文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗匯總,如有什么地方侵權,請聯系本人刪除,謝謝!
請說明一下EJB的幾種類型分別是什么?
會話(Session)Bean、實體(Entity)Bean 、消息驅動的(Message Driven)Bean
會話Bean又可分為有狀態(Stateful)和無狀態(Stateless)兩種
實體Bean可分為Bean管理的持續性(BMP)和容器管理的持續性(CMP)兩種。
請說明一下鎖機制的作用是什么?並且簡述一下Hibernate的悲觀鎖和樂觀鎖機制是什么?
鎖機制的作用是保證共享資源可以進行排他性的訪問
悲觀鎖悲觀的認為在數據處理過程中極有可能存在修改數據的並發事務(包括本系統的其他事務或來自外部系統的事務),於是將處理的數據設置為鎖定狀態。
數據庫中主要是通過數據庫底層的鎖機制才能保證真正的數據訪問排他性。
缺點:並發量不高,效率低;
樂觀鎖對並發事務持樂觀態度(認為對數據的並發操作不會經常性的發生),通過更加寬松的鎖機制來解決由於悲觀鎖排他性的數據訪問對系統性能造成的嚴重影響。最常見的樂觀鎖是通過數據版本標識來實現的
redis為什么是單線程?
多線程不一定比單線程效率高,多線程的本質就是CPU通過輪換時間片執行不同的線程,看似多個線程一起執行,但是卻承擔線程上下文切換的代價。
而對於Redis這樣的內存數據庫來說,沒有上下文的切換的單線程效率是最高的。Redis用單個CPU綁定一塊內存的數據,然后針對這塊內存的數據進行多次讀寫操作都是在一個CPU上完成的。
請你談談Java中線程如何實現,以及如何實現多線程,線程安全在Java中是如何實現的,線程的工作區是哪里
Java多線程有三種實現方式
(1)繼承Thread類,重寫run函數
(2)實現Runnable接口,重寫run函數
開啟線程:Thread t = new Thread(對象) //創建線程對象
t.start()
(3)實現Callable接口,重寫call函數
Callable是類似於Runnable的接口,實現Callable接口的類和實現Runnable的類都是可被其它線程執行的任務。
Callable和Runnable有幾點不同:
①Callable規定的方法是call(),而Runnable規定的方法是run()
②Callable的任務執行后可返回值,而Runnable的任務是不能返回值的
③call()方法可拋出異常,而run()方法是不能拋出異常的。
④運行Callable任務可拿到一個Future對象,Future表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並檢索計算的結果.通過Future對象可了解任務執行情況,可取消任務的執行,還可獲取任務執行的結果
線程不安全的原因:
在操作系統中,線程是不擁有資源的,進程是擁有資源的。而線程是由進程創建的,一個進程可以創建多個線程,這些線程共享着進程中的資源。所以,當線程一起並發運行時,同時對一個數據進行修改,就可能會造成數據的不一致性
線程安全的解決機制:
-
加鎖。
-
鎖能使其保護的代碼以串行的形式來訪問,當給一個復合操作加鎖后,能使其成為原子操作。一種錯誤的思想是只要對寫數據的方法加鎖,其實這是錯的,對數據進行操作的所有方法都需加鎖,不管是讀還是寫。
-
加鎖時需要考慮性能問題,不能總是一味地給整個方法加鎖synchronized就了事了,應該將方法中不影響共享狀態且執行時間比較長的代碼分離出去。
-
加鎖的含義不僅僅局限於互斥,還包括可見性。為了確保所有線程都能看見最新值,讀操作和寫操作必須使用同樣的鎖對象。
-
-
不共享狀態
-
無狀態對象: 無狀態對象一定是線程安全的,因為不會影響到其他線程。
-
線程關閉: 僅在單線程環境下使用。
-
-
不可變對象
可以使用final修飾的對象保證線程安全,由於final修飾的引用型變量(除String外)不可變是指引用不可變,但其指向的對象是可變的,所以此類必須安全發布,也即不能對外提供可以修改final對象的接口。
線程的工作區
Java內存模型分為主內存,和工作內存。主內存是所有的線程所共享的,工作內存是每個線程自己有一個,不是共享的。
每條線程還有自己的工作內存,線程的工作內存中保存了被該線程使用到的變量的主內存副本拷貝。線程對變量的所有操作(讀取、賦值),都必須在工作內存中進行,而不能直接讀寫主內存中的變量。不同線程之間也無法直接訪問對方工作內存中的變量,線程間變量值的傳遞均需要通過主內存來完成
感謝
牛客網
萬能的網絡
以及勤勞的自己
關注公眾號: 歸子莫,獲取更多的資料,還有更長的學習計划