Java高級面試題及答案【第二部分】

談一談對MySQL InnoDB的認識

介紹:前端

InnoDB引擎是MySQL數據庫的一個重要的存儲引擎,和其餘存儲引擎相比,InnoDB引擎的優勢是支持兼容ACID的事務(相似於PostgreSQL),以及參數完整性(有外鍵)等。如今Innobase實行雙認證受權.MySQL5.5.5之後默認的存儲引擎都是InnoDB引擎。java

特色是:程序員

一、具備較好的事務支持:支持4個事務隔離級別,支持多版本讀算法

二、行級鎖定:經過索引實現,全表掃描仍然會是表鎖,注意間隙鎖的影響spring

三、讀寫阻塞與事務隔離級別相關數據庫

四、具備很是高效的緩存特性:能緩存索引,也能緩存數據設計模式

五、整個表和主鍵以Cluster方式存儲,組成一顆平衡樹緩存

六、全部Secondary Index都會保存主鍵信息安全

適用場景:服務器

一、須要事務支持(具備較好的事務特性)

二、行級鎖定對高併發有很好的適應能力,但須要確保查詢是經過索引完成

三、數據更新較爲頻繁的場景

四、數據一致性要求較高

五、硬件設備內存較大,能夠利用InnoDB較好的緩存能力來提升內存利用率,儘量減小磁盤IO


談一談數據庫事務的隔離級別?

一、Read uncommitted(讀未提交)就是一個事務能夠讀取另外一個未提交事務的數據。

二、Read committed(讀提交)就是一個事務要等另外一個事務提交後才能讀取數據。

三、Repeatable read(重複讀)就是在開始讀取數據(事務開啓)時,再也不容許修改操做。

四、Serializable(序列化)在該級別下,事務串行化順序執行,能夠避免髒讀、不可重複讀與幻讀。是最高的事務隔離級別,可是這種事務隔離級別效率低下,比較耗數據庫性能,通常不使用。

事務的做用就是保證數據的一致性、完整性。事務隔離級別越高,在併發下會產生的問題就越少,但同時付出的性能消耗也將越大,所以不少時候必須在併發性和性能之間作一個權衡。因此設立了幾種事務隔離級別,以便讓不一樣的項目能夠根據本身項目的併發狀況選擇合適的事務隔離級別,對於在事務隔離級別以外會產生的併發問題,在代碼中作補償。


MySQL主備同步的基本原理

MySQL支持單向、異步複製,複製過程當中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。

MySQL複製是基於主服務器在二進制日誌中跟蹤全部對數據庫的更改。所以,要進行復制,必須在主服務器上啓用二進制日誌。每一個從服務器從主服務器接收主服務器已經記錄到日誌的數據。

當一個從服務器鏈接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,並在本機上執行相同的更新。而後封鎖並等待主服務器通知新的更新。從服務器執行備份不會干擾主服務器,在備份過程當中主服務器能夠繼續處理更新。


Java語言中一個顯著的特色就是引入了垃圾回收機制,這個你們都清楚,垃圾回收的概念這裏也不作介紹,重點是垃圾回收是在何時開始?對什麼東西,作了什麼事情?

GC什麼時候開始:

全部的回收器類型都是基於分代技術來實現的,那就必需要清楚對象按其生命週期是如何劃分的。

  • 年輕代:劃分爲三個區域:原始區(Eden)和兩個小的存活區(Survivor),兩個存活區按功能分爲From和To。絕大多數的對象都在原始區分配,超過一個垃圾回收操做仍然存活的對象放到存活區。垃圾回收絕大部分發生在年輕代。

  • 年老代:存儲年輕代中通過多個回收週期仍然存活的對象,對於一些大的內存分配,也可能直接分配到永久代。

  • 持久代:存儲類、方法以及它們的描述信息,這裏基本不產生垃圾回收。

有了以上這些鋪墊以後開始回答GC什麼時候開始:

Eden內存滿了以後,開始Minor GC(從年輕代空間回收內存被稱爲 Minor GC);升到老年代的對象所需空間大於老年代剩餘空間時開始Full GC(但也可能小於剩餘空間時,被HandlePromotionFailure參數強制Full GC)

對什麼東西操做,即垃圾回收的對象是什麼:

從root開始搜索沒有可達對象,並且通過第一次標記、清理後,仍然沒有復活的對象。

作了什麼東西:

主要作了清理對象,整理內存的工做。具體的引伸以下

垃圾回收器的類型:

  • 串行垃圾回收器(Serial Garbage Collector)

  • 並行垃圾回收器(Parallel Garbage Collector)

  • 併發標記掃描垃圾回收器(CMS Garbage Collector)

  • G1垃圾回收器(G1 Garbage Collector)

垃圾回收算法:

  • 引用計數法

  • 標記清除法

  • 複製算法

  • 標記壓縮算法

  • 分代算法

  • 分區算法

以上這些,能夠本身瞭解一下,這裏列舉幾篇相關文章:
JVM的內存區域劃分
JVM知識點梳理
JVM內存分配與回收
JVM內存管理機制
Java虛擬機學習 - 垃圾收集器


類在虛擬機中的加載過程

加載Loading:

經過一個類的全限定名來獲取一個二進制字節流、將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構、在內存中生成一個表明這個類的java.lang.Class對象,做爲方法區這個類的各類數據的訪問入口。

驗證Verification:

確保Class文件的字節流中包含的信息符合當前虛擬機的要求,並不會危害虛擬機的自身安全。

準備Preparation:

正式爲類變量分配內存並設置類變量初始值。

解析Resolution:

虛擬機將常量池內的符號引用替換爲直接引用的過程。

初始化Initialization:

類加載過程的最後一步,到了這個階段才真正開始執行類中定義的Java程序代碼。

使用Using:

根據你寫的程序代碼定義的行爲執行。

卸載Unloading:

GC負責卸載,這部分通常不用討論。

以上這些拋磚引玉,歡迎留言更清晰的類加載過程,相關文章能夠閱讀:
類加載器詳解
詳解java類的生命週期
談談我對面向對象以及類與對象的理解


強引用、軟引用、弱引用、虛引用與GC的關係

強引用:new出的對象之類的引用,只要強引用還在,永遠不會回收。

軟引用:引用但非必須的對象,內存溢出異常以前回收。

弱引用:非必須的對象,對象只能生存到下一次垃圾收集發生以前。

虛引用:對生存時間無影響,在垃圾回收時獲得通知。

這個相對好理解了,相關閱讀以下:
Java 如何有效地避免OOM:善於利用軟引用和弱引用


說一下spring中Bean的做用域

singleton:

Spring IoC容器中只會存在一個共享的Bean實例,不管有多少個Bean引用它,始終指向同一對象。Singleton做用域是Spring中的缺省做用域。

prototype:

每次經過Spring容器獲取prototype定義的bean時,容器都將建立一個新的Bean實例,每一個Bean實例都有本身的屬性和狀態,而singleton全局只有一個對象。

request:

在一次Http請求中,容器會返回該Bean的同一實例。而對不一樣的Http請求則會產生新的Bean,並且該bean僅在當前Http Request內有效。

session:

在一次Http Session中,容器會返回該Bean的同一實例。而對不一樣的Session請求則會建立新的實例,該bean實例僅在當前Session內有效。

global Session:

在一個全局的Http Session中,容器會返回該Bean的同一個實例,僅在使用portlet context時有效。


說一下spring中Bean的生命週期

  • 實例化一個Bean,也就是咱們一般說的new。

  • 按照Spring上下文對實例化的Bean進行配置,也就是IOC注入。

  • 若是這個Bean實現了BeanNameAware接口,會調用它實現的setBeanName(String beanId)方法,此處傳遞的是Spring配置文件中Bean的ID。

  • 若是這個Bean實現了BeanFactoryAware接口,會調用它實現的setBeanFactory(),傳遞的是Spring工廠自己(能夠用這個方法獲取到其餘Bean)。

  • 若是這個Bean實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文。

  • 若是這個Bean關聯了BeanPostProcessor接口,將會調用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor常常被用做是Bean內容的更改,而且因爲這個是在Bean初始化結束時調用After方法,也可用於內存或緩存技術。

  • 若是這個Bean在Spring配置文件中配置了init-method屬性會自動調用其配置的初始化方法。

  • 若是這個Bean關聯了BeanPostProcessor接口,將會調用postAfterInitialization(Object obj, String s)方法。

  • 當Bean再也不須要時,會通過清理階段,若是Bean實現了DisposableBean接口,會調用其實現的destroy方法。

  • 最後,若是這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷燬方法。


對Spring中依賴注入兩種方式的認識

兩種注入方式爲:構造方法注入和設值注入

  1. 設值注入與傳統的JavaBean的寫法更類似,程序員更容易理解、接受,經過setter方式設定依賴關係顯得更加直觀、明顯;

  2. 對於複雜的依賴關係,若是採用構造注入,會致使構造器過於臃腫,難以閱讀。Spring在建立Bean實例時,須要同時實例化其依賴的所有實例,於是會產生浪費。而使用設置注入,則避免這下問題;

  3. 在某些屬性可選的狀況下,多參數的構造器更加笨拙,官方更鼓勵使用設值注入。

  4. 構造注入能夠在構造器中決定依賴關係的注入順序,優先依賴的優先注入。

  5. 對於依賴關係無須變化的Bean,構造注入更有用處,由於沒有setter方法,全部的依賴關係所有在構造器內設定,所以,不用擔憂後續代碼對依賴關係的破壞。

  6. 構造注入使依賴關係只能在構造器中設定,則只有組件的建立者才能改變組件的依賴關係。對組件的調用者而言,組件內部的依賴關係徹底透明,更符合高內聚的原則。

  7. 設值注入不會重寫構造方法的值。若是咱們對同一個變量同時使用了構造方法注入又使用了設置方法注入的話,那麼構造方法將不能覆蓋由設值方法注入的值。

  8. 建議採用以設值注入爲主,構造注入爲輔的注入策略。對於依賴關係無須變化的注入,儘可能採用構造注入;而其餘的依賴關係的注入,則考慮採用set注入。


Spring框架中都用到了哪些設計模式?

  • 代理模式:在AOP和remoting中被用的比較多。

  • 單例模式:在spring配置文件中定義的bean默認爲單例模式。

  • 模板方法模式:用來解決代碼重複的問題。

  • 前端控制器模式:Spring提供了DispatcherServlet來對請求進行分發。

  • 依賴注入模式:貫穿於BeanFactory / ApplicationContext接口的核心理念。

  • 工廠模式:BeanFactory用來建立對象的實例。


BeanFactory 和ApplicationContext的區別

BeanFactory和ApplicationContext都是接口,而且ApplicationContext是BeanFactory的子接口。

BeanFactory是Spring中最底層的接口,提供了最簡單的容器的功能,只提供了實例化對象和拿對象的功能。而ApplicationContext是Spring的一個更高級的容器,提供了更多的有用的功能。

ApplicationContext提供的額外的功能:國際化的功能、消息發送、響應機制、統一加載資源的功能、強大的事件機制、對Web應用的支持等等。

加載方式的區別:BeanFactory採用的是延遲加載的形式來注入Bean;ApplicationContext則相反的,它是在Ioc啓動時就一次性建立全部的Bean,好處是能夠立刻發現Spring配置文件中的錯誤,壞處是形成浪費。


這一篇先總結這些,歡迎關注個人公衆號「Java知音」,只推送有價值的文章!

相關文章
相關標籤/搜索