二十道面試題成都至少16k

面試題:
HashMap底層實現原理,紅黑樹,B+樹,B樹的結構原理,volatile關鍵字,CAS(比較與交換)實現原理
Spring的AOP和IOC是什麼?使用場景有哪些?Spring事務,事務的屬性,傳播行爲,數據庫隔離級別
Spring和SpringMVC,MyBatis以及SpringBoot的註解分別有哪些?SpringMVC的工作原理,SpringBoot框架的優點,MyBatis框架的優點
SpringCould組件有哪些,他們的作用是什麼?(說七八個)微服務的CAP是什麼?
設計模式(說五六個)
Redis支持的數據類型以及使用場景,持久化,哨兵機制,緩存擊穿,緩存穿透
線程是什麼,有幾種實現方式,它們之間的區別是什麼,線程池實現原理,JUC併發包,ThreadLocal與Lock和Synchronize區別,voliate關鍵字的作用
分佈式事務(不同系統之間如何保證數據的一致性(A系統寫入數據,B系統因爲某些原因沒有寫入成功,造成數據不一致))
安全性問題(數據篡改(拿到別人的URL,篡改數據(金額)發送給系統))
索引使用的限制條件,sql優化有哪些,數據同步問題(緩存,數據庫數據同步)
初始化Bean對象有幾個步驟,它的生命週期
JVM內存模型,算法,垃圾回收器,調優,類加載機制(雙親委派)
如何設計一個秒殺系統,(高併發高可用分佈式集羣)
悲觀鎖,樂觀鎖,讀寫鎖,行鎖,表鎖,自旋鎖,死鎖,分佈式鎖,線程同步鎖,公平鎖,非公平鎖分別是什麼
堆溢出,棧溢出的出現場景以及解決方案
說出幾種MQ之間的區別,以及爲什麼使用這種MQ,消息重複發送(冪等性),消息發送失敗,消息掉包,長時間收不到消息,發送的消息太大造成接收不成功
單點登錄實現原理
假如有上億條數據,你如何快速找到其中一條你想要的數據(幾種簡單的算法)
Dubbo的運行原理,支持什麼協議,與SpringCould相比它爲什麼效率要高一些,Zookeeper底層原理
假如你帶一個團隊,讓你設計一個系統,你需要考慮哪些
說明:這裏的答案我後面慢慢補,你們先看着,如果覺得自己技術能力強的可以在評論下方留言,儘量精簡語言將知識點擴展多些,合適的我會採用

答案:

HashMap底層實現原理,紅黑樹,B+樹,B樹的結構原理,volatile關鍵字,CAS(比較與交換)實現原理
首先HashMap是Map的一個實現類,而Map存儲形式是鍵值對(key,value)的。可以看成是一個一個的Entry。Entry所存放的位置是由key來決定的。

Map中的key是無序的且不可重複的,所有的key可以看成是一個set集合,如果出現Map中的key如果是自定義類的對象,則必須重寫hashCode和equals方法,因爲如果不重寫,使用的是Object類中的hashCode和equals方法,比較的是內存地址值不是比內容。

Map中的value是無序的可重複的,所有的value可以看成是Collection集合,Map中的value如果是自定義類的對象必須重寫equals方法。

至於要重寫hashCode和equals分別做什麼用,拿hashMap底層原理來說:

當我們向HashMap中存放一個元素(k1,v1),先根據k1的hashCode方法來決定在數組中存放的位置。

如果這個位置沒有其它元素,將(k1,v1)直接放入Node類型的數組中,這個數組初始化容量是16,默認的加載因子是0.75,也就是當元素加到12的時候,底層會進行擴容,擴容爲原來的2倍。如果該位置已經有其它元素(k2,v2),那就調用k1的equals方法和k2進行比較二個元素是否相同,如果結果爲true,說明二個元素是一樣的,用v1替換v2,如果返回值爲false,二個元素不一樣,就用鏈表的形式將(k1,v1)存放。

不過當鏈表中的數據較多時,查詢的效率會下降,所以在JDK1.8版本後做了一個升級,就是當鏈表中的元素達到8時,會將鏈表替換成紅黑樹,來提高查找效率。因爲對於搜索,插入,刪除操作多的情況下,使用紅黑樹的效率要高一些。

原因是因爲紅黑樹是一種特殊的二叉查找樹,二叉查找樹所有節點的左子樹都小於該節點,所有節點的右子樹都大於該節點,就可以通過大小比較關係來進行快速的檢索。

在紅黑樹上插入或者刪除一個節點之後,紅黑樹就發生了變化,可能不滿足紅黑樹的5條性質,也就不再是一顆紅黑樹了,而是一顆普通的樹,可以通過左旋和右旋,使這顆樹重新成爲紅黑樹。紅黑樹的5條性質(根節點是黑色,每個節點是黑色或者是紅色,每個葉子節點是黑色,如果一個節點是紅色它的子節點必須是黑色的,從一個節點到該節點的子孫外部節點的所有路徑上包含相同數目的黑點)



而且像這種二叉樹結構比較常見的使用場景是Mysql二種引擎的索引,Myisam使用的是B樹,InnoDB使用的是B+樹。

首先B樹它的每個節點都是Key.value的二元組,它的key都是從左到右遞增的排序,value中存儲數據。這種模式在讀取數據方面的性能很高,因爲有單獨的索引文件,Myisam 的存儲文件有三個.frm是表的結構文件,.MYD是數據文件,.MYI是索引文件。不過Myisam 也有些缺點它只支持表級鎖,不支持行級鎖也不支持事務,外鍵等,所以一般用於大數據存儲。



然後是InnoDB,它的存儲文件相比Myisam少一個索引文件,它是以 ID 爲索引的數據存儲,數據現在都被存在了葉子結點,索引在非葉結點上。而這些節點分散在索引頁上。在InnoDB裏,每個頁默認16KB,假設索引的是8B的long型數據,每個key後有個頁號4B,還有6B的其他數據,那麼每個頁的扇出係數爲16KB/(8B+4B+6B)≈1000,即每個頁可以索引1000個key。在高度h=3時,s=1000^3=10億!!也就是說,InnoDB通過三次索引頁的I/O,即可索引10億的key,而非葉節點這一行存儲的索引,數量就多了,I/O的次數就少了。而Myisam在每個節點都存儲數據和索引,這樣就減少了每頁存儲的索引數量。而且InnoDB它還支持行級,表級鎖,也支持事務,外鍵.



另外對於HashMap實際使用過程中還是會出現一些線程安全問題:

HashMap是線程不安全的,在多線程環境下,使用Hashmap進行put操作會引起死循環,導致CPU利用率接近100%,而且會拋出併發修改異常,導致原因是併發爭取線程資源,修改數據導致的,一個線程正在寫,一個線程過來爭搶,導致線程寫的過程被其他線程打斷,導致數據不一致。

HashTable是線程安全的,只不過實現代價卻太大了,簡單粗暴,get/put所有相關操作都是synchronized的,這相當於給整個哈希表加了一把大鎖。多線程訪問時候,只要有一個線程訪問或操作該對象,那其他線程只能阻塞,相當於將所有的操作串行化,在競爭激烈的併發場景中性能就會非常差。

爲了應對hashmap在併發環境下不安全問題可以使用,ConcurrentHashMap大量的利用了volatile,CAS等技術來減少鎖競爭對於性能的影響。

在JDK1.7版本中ConcurrentHashMap避免了對全局加鎖,改成了局部加鎖(分段鎖),分段鎖技術,將數據分成一段一段的存儲,然後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個段數據的時候,其他段的數據也能被其他線程訪問,能夠實現真正的併發訪問。不過這種結構的帶來的副作用是Hash的過程要比普通的HashMap要長。

所以在JDK1.8版本中CurrentHashMap內部中的value使用volatile修飾,保證併發的可見性以及禁止指令重排,只不過volatile不保證原子性,使用爲了確保原子性,採用CAS(比較交換)這種樂觀鎖來解決。

CAS 操作包含三個操作數 —— 內存位置(V)、預期原值(A)和新值(B)。

如果內存地址裏面的值和A的值是一樣的,那麼就將內存裏面的值更新成B。CAS是通過無限循環來獲取數據的,若果在第一輪循環中,a線程獲取地址裏面的值被b線程修改了,那麼a線程需要自旋,到下次循環纔有可能機會執行。

volatile有三個特性:可見性,不保證原子性,禁止指令重排。

可見性:線程1從主內存中拿數據1到自己的線程工作空間進行操作(假設是加1)這個時候數據1已經改爲數據2了,將數據2寫回主內存時通知其他線程(線程2,線程3),主內存中的數據1已改爲數據2了,讓其他線程重新拿新的數據(數據2)。

不保證原子性:線程1從主內存中拿了一個值爲1的數據到自己的工作空間裏面進行加1的操作,值變爲2,寫回主內存,然後還沒有來得及通知其他線程,線程1就被線程2搶佔了,CPU分配,線程1被掛起,線程2還是拿着原來主內存中的數據值爲1進行加1,值變成2,寫回主內存,將主內存值爲2的替換成2,這時線程1的通知到了,線程2重新去主內存拿值爲2的數據。

禁止指令重排:首先指令重排是程序執行的時候不總是從上往下執行的,就像高考答題,可以先做容易的題目再做難的,這時做題的順序就不是從上往下了。禁止指令重排就杜絕了這種情況。

(一般面試官開始問你會從java基礎問起,一問大多數會問到集合這一塊,而集合問的較多的是HashMap,這個時候你就可以往這些方向帶着面試官問你,而且擴展的深度也夠,所以上面的乾貨夠你說個十來分鐘吧,第一個問題拿下後,面試官心裏至少簡單你的基礎夠紮實,第一印象分就留下了)

Spring的AOP和IOC是什麼?使用場景有哪些?Spring事務與數據庫事務,傳播行爲,數據庫隔離級別
AOP:面向切面編程。

即在一個功能模塊中新增其他功能,比方說你要下樓取個快遞,你同事對你說幫我也取一下唄,你就順道取了。在工作中如果系統中有些包和類中沒有使用AOP,例如日誌,事務和異常處理,那麼就必須在每個類和方法中去實現它們。 代碼糾纏每個類和方法中都包含日誌,事務以及異常處理甚至是業務邏輯。在一個這樣的方法中,很難分清代碼中實際做的是什麼處理。AOP 所做的就是將所有散落各處的事務代碼集中到一個事務切面中。

比方說我現在要弄一個日誌,記錄某些個接口調用的方法時間。使用Aop我可以在這個接口前插入一段代碼去記錄開始時間,在這個接口後面去插入一段代碼記錄結束時間。

又或者你去訪問數據庫,而你不想管事務(太煩),所以,Spring在你訪問數據庫之前,自動幫你開啓事務,當你訪問數據庫結束之後,自動幫你提交/回滾事務!

異常處理你可以開啓環繞通知,一旦運行接口報錯,環繞通知捕獲異常跳轉異常處理頁面。

Spring AOP使用的動態代理,所謂的動態代理就是說AOP框架不會去修改字節碼,而是在內存中臨時爲方法生成一個AOP對象,這個AOP對象包含了目標對象的全部方法,並且在特定的切點做了增強處理,並回調原對象的方法。它的動態代理主要有兩種方式,JDK動態代理和CGLIB動態代理。JDK動態代理通過反射來接收被代理的類,並且要求被代理的類必須實現一個接口。JDK動態代理的核心是InvocationHandler接口和Proxy類。如果目標類沒有實現接口,那麼Spring AOP會選擇使用CGLIB來動態代理目標類。CGLIB是一個代碼生成的類庫,可以在運行時動態的生成某個類的子類,注意,CGLIB是通過繼承的方式做的動態代理,因此如果某個類被標記爲final,那麼它是無法使用CGLIB做動態代理的。

IOC:依賴注入或者叫做控制反轉。

正常情況下我們使用一個對象時都是需要new Object()的。而ioc是把需要使用的對象提前創建好,放到spring的容器裏面。

所有需要使用的類都會在spring容器中登記,告訴spring你是個什麼東西,你需要什麼東西,然後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創建、銷燬都由 spring來控制,也就是說控制對象生存週期的不再是引用它的對象,而是spring。DI(依賴注入)其實就是IOC的另外一種說法,其實它們是同一個概念的不同角度描述。

Spring事務與數據庫事務

什麼是事務?事務是訪問並可能更新數據庫中各種數據項的一個程序執行單元,即要麼完全地執行,要麼完全地不執行。

Spring的事務是對數據庫的事務的封裝,最後本質的實現還是在數據庫,假如數據庫不支持事務的話,Spring的事務是沒有作用的
所以說Spring事務的底層依賴MySQL的事務,Spring是在代碼層面利用AOP實現,執行事務的時候使用TransactionInceptor進行攔截,然後處理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章