螞蟻Java一面 1. 二叉搜索樹和平衡二叉樹有什麼關係,強平衡二叉樹(AVL樹)和弱平衡二叉樹(紅黑樹)有什麼區別 二叉搜索樹:也稱二叉查找樹,或二叉排序樹。定義也比較簡單,要麼是一顆空樹,要麼就是具備以下性質的二叉樹: (1)若任意節點的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值; (2)若任意節點的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值; (3)任意節點的左、右子樹也分別爲二叉查找樹; (4)沒有鍵值相等的節點。 平衡二叉樹:在二叉搜索樹的基礎上多了兩個重要的特色 (1)左右兩子樹的高度差的絕對值不能超過1; (2)左右兩子樹也是一顆平衡二叉樹。 紅黑書:紅黑樹是在普通二叉樹上,對每一個節點添加一個顏色屬性造成的,須要同時知足一下五條性質 (1)節點是紅色或者是黑色; (2)根節點是黑色; (3)每一個葉節點(NIL或空節點)是黑色; (4)每一個紅色節點的兩個子節點都是黑色的(也就是說不存在兩個連續的紅色節點); (5)從任一節點到其沒個葉節點的全部路徑都包含相同數目的黑色節點。 區別:AVL樹須要保持平衡,但它的旋轉太耗時,而紅黑樹就是一個沒有AVL樹那樣平衡,所以插入、刪除效率會高於AVL樹,而AVL樹的查找效率顯然高於紅黑樹。 參考文章1:https://blog.csdn.net/qq_25940921/article/details/82183093 參考文章2:https://blog.csdn.net/yang_yulei/article/details/26066409 2. B樹和B+樹的區別,爲何MySQL要使用B+樹 B樹: (1)關鍵字集合分佈在整顆樹中; (2)任何一個關鍵字出現且只出如今一個結點中; (3)搜索有可能在非葉子結點結束; (4)其搜索性能等價於在關鍵字全集內作一次二分查找; B+樹: (1)有n棵子樹的非葉子結點中含有n個關鍵字(b樹是n-1個),這些關鍵字不保存數據,只用來索引,全部數據都保存在葉子節點(b樹是每一個關鍵字都保存數據); (2)全部的葉子結點中包含了所有關鍵字的信息,及指向含這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大順序連接; (3)全部的非葉子結點能夠當作是索引部分,結點中僅含其子樹中的最大(或最小)關鍵字; (4)一般在b+樹上有兩個頭指針,一個指向根結點,一個指向關鍵字最小的葉子結點; (5)同一個數字會在不一樣節點中重複出現,根節點的最大元素就是b+樹的最大元素。 B+樹相比於B樹的查詢優點: (1)B+樹的中間節點不保存數據,因此磁盤頁能容納更多節點元素,更「矮胖」; (2)B+樹查詢必須查找到葉子節點,B樹只要匹配到便可不用管元素位置,所以B+樹查找更穩定(並不慢); (3)對於範圍查找來講,B+樹只需遍歷葉子節點鏈表便可,B樹卻須要重複地中序遍歷 參考文章:https://www.cnblogs.com/xueqiuqiu/articles/8779029.html 3. HashMap如何解決Hash衝突 經過引入單向鏈表來解決Hash衝突。當出現Hash衝突時,比較新老key值是否相等,若是相等,新值覆蓋舊值。若是不相等,新值會存入新的Node結點,指向老節點,造成鏈式結構,即鏈表。 當Hash衝突發生頻繁的時候,會致使鏈表長度過長,以至檢索效率低,因此JDK1.8以後引入了紅黑樹,當鏈表長度大於8時,鏈表會轉換成紅黑書,以此提升查詢性能。 參考文章:https://blog.csdn.net/qedgbmwyz/article/details/79908333 4. epoll和poll的區別,及其應用場景 select和epoll都是I/O多路複用的方式,可是select是經過不斷輪詢監聽socket實現,epoll是當socket有變化時經過回掉的方式主動告知用戶進程實現 參考文章:https://www.cnblogs.com/hsmwlyl/p/10652503.html 5. 簡述線程池原理,FixedThreadPool用的阻塞隊列是什麼? Java線程池的實現原理其實就是一個線程集合workerSet和一個阻塞隊列workQueue。當用戶向線程池提交一個任務(也就是線程)時,線程池會先將任務放入workQueue中。 workerSet中的線程會不斷的從workQueue中獲取線程而後執行。當workQueue中沒有任務的時候,worker就會阻塞,直到隊列中有任務了就取出來繼續執行。 FixedThreadPool使用的是「無界隊列」LinkedBlockingQueue 參考文章:https://blog.csdn.net/wanghao112956/article/details/99938893 6. sychronized和ReentrantLock的區別 (1)ReentrantLock顯示得到、釋放鎖,synchronized隱式得到釋放鎖 (2)ReentrantLock可響應中斷、可輪迴,synchronized是不能夠響應中斷的,爲處理鎖的不可用性提供了更高的靈活性 (3)ReentrantLock是API級別的,synchronized是JVM級別的 (4)ReentrantLock能夠實現公平鎖 (5)ReentrantLock經過Condition能夠綁定多個條件 參考文章:https://blog.csdn.net/zxd8080666/article/details/83214089 7. sychronized的自旋鎖、偏向鎖、輕量級鎖、重量級鎖,分別介紹和聯繫 自旋鎖:果持有鎖的線程能在很短期內釋放鎖資源,那麼那些等待競爭鎖的線程就不須要作內核態和用戶態之間的切換進入阻塞掛起狀態,它們只須要等一等(自旋), 等持有鎖的線程釋放鎖後便可當即獲取鎖,這樣就避免用戶線程和內核的切換的消耗。 偏向鎖:顧名思義,它會偏向於第一個訪問鎖的線程,若是在運行過程當中,同步鎖只有一個線程訪問,不存在多線程爭用的狀況,則線程是不須要觸發同步的,減小加鎖/解鎖 的一些CAS操做(好比等待隊列的一些CAS操做),這種狀況下,就會給線程加一個偏向鎖。 若是在運行過程當中,遇到了其餘線程搶佔鎖,則持有偏向鎖的線程會被掛起,JVM會 消除它身上的偏向鎖,將鎖恢復到標準的輕量級鎖。 輕量級鎖:輕量級鎖是由偏向所升級來的,偏向鎖運行在一個線程進入同步塊的狀況下,當第二個線程加入鎖爭用的時候,偏向鎖就會升級爲輕量級鎖; 重量級鎖:咱們知道,咱們要進入一個同步、線程安全的方法時,是須要先得到這個方法的鎖的,退出這個方法時,則會釋放鎖。若是獲取不到這個鎖的話,意味着有別的線程在 執行這個方法,這時咱們就會立刻進入阻塞的狀態,等待那個持有鎖的線程釋放鎖,而後再把咱們從阻塞的狀態喚醒,咱們再去獲取這個方法的鎖。這種獲取不到鎖就立刻進入阻 塞狀態的鎖,咱們稱之爲重量級鎖。 參考文章:https://blog.csdn.net/zqz_zqz/article/details/70233767 參考文章:https://www.cnblogs.com/myseries/p/10773078.html 8. HTTP有哪些問題,加密算法有哪些,針對不一樣加密方式可能產生的問題,及其HTTPS是如何保證安全傳輸的 HTTP的不足: 通訊使用明文,內容可能會被竊聽; 不驗證通訊方的身份,所以有可能遭遇假裝; 沒法證實報文的完整性,有可能已遭篡改; 經常使用加密算法:MD5算法、DES算法、AES算法、RSA算法 參考文章:https://blog.csdn.net/baidu_22254181/article/details/82594072螞蟻Java二面 1. 設計模式有哪些大類,及熟悉其中哪些設計模式 建立型模式、結構型模式、行爲型模式 參考文章:http://c.biancheng.net/design_pattern/ 2. volatile關鍵字,他是如何保證可見性,有序性 volatile能夠保證線程可見性且提供了必定的有序性,可是沒法保證原子性。在JVM底層volatile是採用「內存屏障」來實現的。 觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的彙編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令, lock前綴指令實際上至關於一個內存屏障(也成內存柵欄),內存屏障會提供3個功能: I. 它確保指令重排序時不會把其後面的指令排到內存屏障以前的位置,也不會把前面的指令排到內 存屏障的後面;即在執行到內存屏障這句指令時,在它前面的操做已經所有完成; II. 它會強制將對緩存的修改操做當即寫入主存; III. 若是是寫操做,它會致使其餘CPU中對應的緩存行無效。 參考文章:https://blog.csdn.net/summerZBH123/article/details/80547516 3. Java的內存結構,堆分爲哪幾部分,默認年齡多大進入老年代 Java的內存結構:程序計數器、虛擬機棧、本地方法棧、堆、方法區。 Java虛擬機根據對象存活的週期不一樣,把堆內存劃分爲幾塊,通常分爲新生代、老年代和永久代。 默認的設置下,當對象的年齡達到15歲的時候,也就是躲過15次Gc的時候,他就會轉移到老年代中去躲過15次GC以後進入老年代。 4. ConcurrentHashMap如何保證線程安全,jdk1.8有什麼變化 JDK1.7:使用了分段鎖機制實現ConcurrentHashMap,ConcurrentHashMap在對象中保存了一個Segment數組,即將整個Hash表劃分爲多個分段; 而每一個Segment元素,即每一個分段則相似於一個Hashtable;這樣,在執行put操做時首先根據hash算法定位到元素屬於哪一個Segment,而後對該 Segment加鎖便可。所以,ConcurrentHashMap在多線程併發編程中但是實現多線程put操做,不過其最大併發度受Segment的個數限制。 JDK1.8: 底層採用數組+鏈表+紅黑樹的方式實現,而加鎖則採用CAS和synchronized實現 參考文章:https://blog.csdn.net/weixin_44460333/article/details/86770169 5. 爲何ConcurrentHashMap底層爲何要紅黑樹 由於發生hash衝突的時候,會在鏈表上新增節點,可是鏈表過長的話會影響檢索效率,引入紅黑書能夠提升插入和查詢的效率。 6. 如何作的MySQL優化 MySQL的優化有多種方式,咱們能夠從如下幾個方面入手: 存儲引擎的選擇、字段類型的選擇、索引的選擇、分區分表、主從複製、讀寫分離、SQL優化。詳細優化請查看參考文章 參考文章:https://blog.csdn.net/zls986992484/article/details/52860496 7. 講一下oom以及遇到這種狀況怎麼處理的,是否使用過日誌分析工具 OOM,全稱「Out Of Memory」,翻譯成中文就是「內存用完了」,當JVM由於沒有足夠的內存來爲對象分配空間而且垃圾回收器也已經沒有空間可回收時,就會拋出這個error。 處理過程:首先經過內存映射分析工具 如 Eclipse Memory Analyzer 堆 dump出的異常堆轉儲進行快照解析確認內存中的對象是不是必要的, 也就是先分清楚是 內存泄漏 Memory Leak 仍是Memory Overflow 若是是內存泄漏 可經過工具進一步查看泄露的對象到GC Roots的引用鏈, 就能找到泄露對象是怎麼經過路徑與 GC Roots 相關聯致使垃圾收集器沒法回收他們若是不存在泄露 就檢查堆參數 -Xmx 與 -Xms 與機器物理 內存對比是否還能夠調大 從代碼上檢測 是不是某些對象的生命週期過長持有狀態時間過長 嘗試減小代碼運行期間的內存消耗。 參考文章:https://www.cnblogs.com/ThinkVenus/p/6805495.html螞蟻Java三面 1. 項目介紹 2. 大家怎麼保證Redis緩存和數據庫的數據一致性? 能夠經過雙刪延時策略來保證他們的一致性。 參考文章:https://blog.kido.site/2018/12/07/db-and-cache-02/ 3. Redis緩存雪崩?擊穿?穿透? 緩存雪崩:緩存同一時間大面積的失效,因此,後面的請求都會落到數據庫上,形成數據庫短期內承受大量請求而崩掉。 緩存擊穿:key對應的數據存在,但在redis中過時,此時如有大量併發請求過來,這些請求發現緩存過時通常都會從後端DB加載數據並回設到緩存,這個時候大併發的請求可能會瞬間把後端DB壓垮。 緩存穿透:key對應的數據在數據源並不存在,每次針對此key的請求從緩存獲取不到,請求都會到數據源,從而可能壓垮數據源。好比用一個不存在的用戶id獲取用戶信息,不論緩存仍是數據庫都沒有,若黑客利用此漏洞進行攻擊可能壓垮數據庫。 4. 你熟悉哪些消息中間件,有作過性能比較? RocketMQ、RabbitMQ、ActiveMQ、Kafka 參考文章:https://blog.csdn.net/wqc19920906/article/details/82193316