java 面試題積累

1、ngix的負載均衡機制

(1)輪詢(默認)逐一訪問後端服務器,每一個請求按順序逐一分配到不同的後端服務器,如果後端服務器down掉了,則能自動剔除

(2)ip_hash 請求按訪問IP的hash結果分配,這樣來自同一個IP的訪客固定訪問一個後端服務器,有效解決了動態網頁存在的session共享問題。

  (3) weight是設置權重,用於後端服務器性能不均的情況,訪問比率約等於權重之比

(4)fair(第三方)、這是比上面兩個更加智能的負載均衡算法。此種算法可以依據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間來分配請求,響應時間短的優先分配。Nginx本身是不支持fair的,如果需要使用這種調度算法,必須下載Nginx的upstream_fair模塊。

(5) url_hash(第三方)此方法按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,可以進一步提高後端緩存服務器的效率。Nginx本身是不支持url_hash的,如果需要使用這種調度算法,必須安裝Nginx 的hash軟件包。

2、HashMap的底層原理

HashMap 是一種存儲高校但是不保證有序的容器,它的數據結構爲"數組+鏈表/紅黑樹"的結構(當鏈表長度到8以後數據結構改爲紅黑樹),是線程不安全,允許key和value爲null。底層結構數組叫哈希桶,而桶內則是鏈表,鏈表中的節點Node存放着實際的元素。

底層實現了Map<k,v> 的接口並實現了淺拷貝和序列化,HashMap 默認初始值大小爲16 ,初始值大小必須爲2的冪次,如果用戶輸入的不是2的冪,那麼系統自動更新爲輸入值附近的2的冪次,最大大小爲2的30次冪。HashMap的閾值默認爲 0.75,當存儲節點超過該值,對map進行擴容。
每次擴容爲原來的1倍。

在一次put(添加操作)的時候,HashMap 會先進行初始化,如果沒有先進行初始化操作,初始化過程會取比用戶指定容量大的最近2的冪次數作爲數組的初始容量,如果設置了擴容的閾值也一併更新。初始化完成以後繼續put 方法
1.先判斷有沒有初始化
2.在判斷傳入的key是否爲空 就存儲在table(0)位置(及Node首節點,使用CAS來保證添加首節點線程安全)
3.key不爲空就對key進行hash,hash的結果在 & 上數組的長度就得到了位置。
4.如果存儲位置爲空就創建新節點(並使用synchronized鎖保證線程安全),不爲空就說存在hash衝突了。
5.解決衝突HashMap會遍歷整個鏈表,如果有相同的value值就更新,否則創建節點添加到鏈表頭。
6.添加還要判斷存儲節點是否達到閾值,達到閾值要進行擴容。
7.擴容兩倍,擴容的時候使用Arrays.copy() 進行擴容。
8.擴容過後新插入的節點也要重新進行hash 一遍才能插入。
以上這些是一些常用的知識點,但是如果你只是知道以上這些還是不夠的,一般面試官還會問你HashMap 線程安全碼? 當然大家都知道是不安全的,但是要是問你怎麼解決呢? 如果你要是回答加鎖或者回答使用HashTable 基本上就掛了。HashMap是一個線程不安全的容器,在併發操作會出現丟失更新問題,嚴重會導致cpu宕機的,一般報錯爲java.util.ConcurrentModificationException.那我們該怎麼解決呢?
1.使用java類庫提供的collections工具包下的Collections.synchronizedMap(new HashMap()),返回一個線程安全的Map
2.使用併發包(java.util.concurrent)下的ConcurrentHashMap,ConcurrentHashMap採用分段式鎖機制實現線程安全。

java8和java7的區別
Hash1.7 和1.8 最大的不同在於1.8 採用了“數組+鏈表+紅黑樹”的數據結構,在鏈表長度超過8 時,把鏈表轉化成紅黑樹來解決HashMap 因鏈表變長而查詢變慢的問題;
1.7 的底層節點爲Entry,1.8 爲node ,但是本質一樣,都是Map.Entry 的實現
還有就是在存取數據時添加了關於樹結構的遍歷更新與添加操作,並採用了尾插法來避免環形鏈表的產生。

 

3.HashMap的長度爲什麼是2的倍數
在HashMap的操作流程中,首先會對key進行hash算法得到一個索引值,這個索引值就是對應哈希桶數組的索引。爲了得到這個索引值必須對擾動後的數跟數組長度進行取餘運算。即 hash % n (n爲hashmap的長度),又因爲&比%運算快。n如果爲2的倍數,就可以將%轉換爲&,結果就是 hash & (n-1)。所以這就解釋了爲什麼HashMap長度是2的倍數。

& 字符串和%字符串 雖然效果一樣,但是操作效果更高。

Jdk1.8中滿足什麼條件後將鏈表轉化成紅黑樹?

1.putVal方法中是判斷桶內的節點個數是否大於8,

2.還要通過treeifyBin方法中判斷桶內節點中元素總數紅黑樹容量64,小於則繼續擴容,大於則轉爲紅黑樹。

爲什麼int String 更適合做key?

int 和 String 的好處在於hash 出來的值不會改變。如果是一個對象,那麼他們可能會因爲內部引用的改變而hashCode 值的改變,會導致存儲重複的數據或找不到數據的情況。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章