第一次面試
自我介紹,然後問了專案,專案中遇到什麼困難
一些問題
1.hashmap,concurrentHashmap區別是什麼
答:
hashmap是執行緒不安全的,concurrentHashMap是執行緒安全的
2.為什麼hashmap是不安全的?
答:
···多執行緒下擴容死迴圈。JDK1.7中的 HashMap 使用頭插法插入元素,在多執行緒的環境下,擴容的時候有可能導致環形連結串列的出現,形成死迴圈。因此,JDK1.8使用尾插法插入元素,在擴容時會保持連結串列元素原本的順序,不會出現環形連結串列的問題。
···多執行緒的put可能導致元素的丟失。多執行緒同時執行 put 操作,如果計算出來的索引位置是相同的,那會造成前一個 key 被後一個 key 覆蓋,從而導致元素的丟失。此問題在JDK 1.7和 JDK 1.8 中都存在。
···put和get併發時,可能導致get為null。執行緒1執行put時,因為元素個數超出threshold而導致rehash,執行緒2此時執行get,有可能導致這個問題。此問題在JDK 1.7和 JDK 1.8 中都存在。
3.如果想要執行緒安全該怎麼辦?
·使用concurrentHashMap,因為ConcurrentHashMap 選擇了與 HashMap 相同的陣列+連結串列+紅黑樹結構;在鎖的實現上,拋棄了原有的 Segment 分段鎖,採用CAS + synchronized
實現更加低粒度的鎖。將鎖的級別控制在了更細粒度的雜湊桶元素級別,也就是說只需要鎖住這個連結串列頭結點(紅黑樹的根節點),就不會影響其他的雜湊桶元素的讀寫,大大提高了併發度。所以可以保證執行緒安全。
4.ArrayList知道嗎,講一下
ArrayList是 java 集合框架中比較常用的資料結構。繼承自 AbstractList,實現了 List 介面。底層基於陣列實現容量大小動態變化。允許 null 的存在。同時還實現了 RandomAccess、Cloneable、Serializable 介面,所以ArrayList 是支援快速訪問、複製、序列化的。
ArrayList擴容,本質就是計算出新的擴容陣列的size後例項化,並將原有陣列內容複製到新陣列中去。預設情況下,新的容量會是原容量的1.5倍。
5.計算機網路 三次握手四次揮手 。
三次握手機制:
-
第一次握手:客戶端請求建立連線,向服務端傳送一個同步報文(SYN=1),同時選擇一個隨機數 seq = x 作為初始序列號,並進入SYN_SENT狀態,等待伺服器確認。
-
第二次握手:服務端收到連線請求報文後,如果同意建立連線,則向客戶端傳送同步確認報文(SYN=1,ACK=1),確認號為 ack = x + 1,同時選擇一個隨機數 seq = y 作為初始序列號,此時伺服器進入SYN_RECV狀態。
-
第三次握手:客戶端收到服務端的確認後,向服務端傳送一個確認報文(ACK=1),確認號為 ack = y + 1,序列號為 seq = x + 1,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手。
四次揮手機制
-
第一次揮手:客戶端向服務端傳送連線釋放報文(FIN=1),主動關閉連線,同時等待服務端的確認。
- 序列號 seq = u,即客戶端上次傳送的報文的最後一個位元組的序號 + 1
-
第二次揮手:服務端收到連線釋放報文後,立即發出確認報文(ACK=1),確認號 ack = u + 1。
這時 TCP 連線處於半關閉狀態,即客戶端到服務端的連線已經釋放了,但是服務端到客戶端的連線還未釋放。這表示客戶端已經沒有資料傳送了,但是服務端可能還要給客戶端傳送資料。
-
第三次揮手:服務端向客戶端傳送連線釋放報文(FIN=1),主動關閉連線,同時等待客戶端的確認。
- 序列號 seq = w,即服務端上次傳送的報文的最後一個位元組的序號 + 1。
-
第四次揮手:客戶端收到服務端的連線釋放報文後,立即發出確認報文(ACK=1),確認號為 ack = w + 1。
此時,客戶端就進入了
TIME-WAIT
狀態。注意此時客戶端到 TCP 連線還沒有釋放,必須經過 2*MSL(最長報文段壽命)的時間後,才進入CLOSED
狀態。而服務端只要收到客戶端發出的確認,就立即進入CLOSED
狀態。可以看到,服務端結束 TCP 連線的時間要比客戶端早一些。
6.你在你專案裡面什麼地方用到了三次握手?
每一次Controller的請求都用到了TCP三次握手
7.常用資料結構知道哪些,知道幾種排序演算法,時間複雜度是多少。
陣列,連結串列,二叉樹
氣泡排序 O(n^2)
快速排序 O(n·logn)
希爾排序O(nlog2n)
插入排序O(n2)