微信事業羣
時間:20190831 時長:1小時30分
地點:牛客遠程視頻
一分鐘自我介紹
一、上手code
1、手寫字符串的反轉
我的code:
public String stringReserve(String inputString) {
int length = inputString.length();
if(inputString == null || length == 0) {
return null;
}
return reverse(inputString.toCharArray(), 0, length-1);
}
private String reverse(char[] str, int start, int end) {
while (start < end) {
char temp = str[start];
str[start++] = str[end];
str[end--] = temp;
}
return str.toString();
}
2、 手寫雙向鏈表
我的code:
public class LinkedList{
private Node root;
public class Node{
private Object data;
private Node preNode;
private Node next;
}
public Node getRoot(){
return this.root;
}
public void setRoot(Node root) {
this.root = root;
}
}
3、按照順序合併兩個鏈表,手寫代碼
我的code:
public Node merge(LinkedList first, LinkedList second) {
if(first == null && second == null) return null;
if (first != null && second == null) {
return first.getRoot();
}
if (first == null && second != null) {
return second.getRoot();
}
Node newNode;
Node temp;
Node temp1 = new Node();
Node temp2 = new Node();
if (first.getRoot().data < second.getRoot().data) {
newNode = first.root;
temp = newNode.next;
temp1 = temp;
}
else {
newNode = second.root;
temp = newNode.next;
temp2 = temp;
}
while (temp1 != null && temp2 != null) {
if(temp1.data < temp2.data) {
temp.next = temp1;
temp1 = temp1.next;
}
else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
}
if (temp2 != null) {
temp.next = temp2;
}
return newNode;
}
4、手寫快排算法,問了快排的時間複雜度,什麼情況是最差的
我的回答:快排時間最好情況是O(nlogn),最差O(n*n);最差情況是目標排序數組是有序的,基數每次移動都是移動一步,類似於冒泡排序
我的code:
public void quickSort (int[] array, int start, int end) {
if (array == null || array.length == 0) {
return;
}
int i = start, j = end;
int temp = array[start];
while (i < j) {
while(array[j] > temp && i < j) {
--j;
}
while(array[i] <= temp && i < j) {
++i;
}
int x = array[i];
array[i] = array[j];
array[j] = x;
}
array[start] = array[i];
array[start] = temp;
quickSort(array, start, i-1);
quickSort(array, i+1, end);
}
二、技術面試
- “ == ”和equals的區別
== 是比較兩個引用之間是否指向同一個對象,也就是比較兩個引用存儲的地址是否相等
equals在Object中比較的是兩個對象的hashcode,日常我們實現基類時覆蓋Object的equals方法,
例如User時,在equals中對屬性name,age進行比較
- Hash算法你知道哪些?
我只知道一致性hash算法,然後拓展的說了下自己在項目中如何用到一致性哈希
算法的(Dubbo的一致性哈希算法實現負載均衡算法)
- 哈希碰撞的解決方案有哪些?說說開放定址法原理
- HashMap應用的鏈表法
- 開放定製法:感興趣自行百度下,太多了,博主就不囉嗦了
- TreeMap和HashMap 的區別
看過源碼,瞭解TreeMap是基於紅黑樹的,所以元素是有序的
HashMap是基於哈希算法的,元素是亂序存放
- 說說紅黑樹和Avl樹
讀者自行百度?
- 緩存淘汰算法
我的第一想法是Redis的LRU算法,之前看過Redis的源碼,所以直接說了Redis幾種常用的淘汰算法,
包括隨機淘汰算法,FIFO淘汰算法,以及默認算法:刪除不常用的key,使用雙向鏈表維護所有被
使用的key,頻繁使用的key存放在鏈表的表頭附近,淘汰機制只需要淘汰表尾的元素
- TCP三次握手、四次揮手
- HTTP、HTTPS的區別
有必要和讀者說說這兒:
- HTTPS相對於HTTP的文本傳輸變換爲二進制傳輸,安全快捷
- HTTPS添加SSL協議,保障傳輸安全
- HTTPS默認支持長連接,採用多路複用機制
- HTTPS服務端支持反饋更多信息給應用端
- SSL過程
讀者自行百度,博主建議挖透式學習
- 進程和線程的共同點和區別
共同點:擁有CPU的執行權、切換
區別:
- 進程可包含多個線程
- 進程管理資源,線程不能
- 進程之間的切換消耗比線程之間的切換大
- 線程之間共享進程的公共資源
- 進程之間的通信,線程之間的通信
進程之間可以通過RPC、消息中間件、Socket,全局變量等通信
線程之間可以通過共享變量、管道、wait/notify機制
- 你知道協程吧?
不知道?
- 你知道系統中的大小端吧?
不知道?
- 你用過BIO、NIO、AIO,說說他們之間的區別吧
BIO:同步阻塞式,一個socket請求對應一個線程處理,耗時耗資源
NIO:同步非阻塞,socket請求由線程池來處理(boss、worker線程池原理)
AIO:異步化
我另外解釋了下系統底層的實現select、poll、epoll的區別:
- select每次執行select方法,都會從用戶態拷貝所有的fd文件到內核態中,存儲在內核態的數組中,數組大小默認1024個,存放的fd文件數量受限制
- select採用輪訓的方式尋找有事件的fd文件
- 對有事件的fd文件再次拷貝到用戶態做相應的處理
- epoll有三個函數:epoll_create、epoll_ctl、epoll_wait,epoll_create在內核態啓動時創建紅黑樹和就緒隊列,紅黑樹相對於select的數組所容納的fd文件數量更多,效率更高
- epoll_ctl負責將用戶態的fd文件符拷貝到內核的紅黑樹中,並且制定相應的回調接口,當fd文件符有事件時,回調接口,將fd文件移動到就緒隊列中
- epoll_wait負責監聽就緒隊列是否有就緒的fd文件,有的話拷貝到用戶態,否則,繼續睡眠,等待被喚醒
- 內核態與用戶態的交互過程
我按照自己理解說了下線程之間的上下文切換,進程之間的切換,主要是一些信息的拷貝,比較耗時,
如果切換次數過多的話,會對CPU的性能帶來影響。
- 怎麼看系統的CPU信息
我說到常用的TOP命令會看到系統的CPU使用率,內存等信息;還有vmstat查看上下文切換信息
- 給了我一段代碼
String a = "aaaaaa";
int b;
int test (int i) {
b = i;
}
int main () {
int temp = 0;
int c = test(temp);
return c;
}
問在進程中這些信息的佈局
我的回答:
變量a:首先字符串在JVM中是常量,所以a變量肯定存放在常量池中,而常量池存放在JVM中的永久代中。
變量i、b、temp、c:基本變量類型和臨時變量都是存放在JVM棧的棧楨中,每個棧楨包含臨時變量,變量值等信息
方法test:方法是被線程調用的,所以方法存在於棧中,調用方法的過程進棧,返回方法的過程是出棧
- 給了一段代碼,問我char和int各佔幾個字節,這幾個變量一共佔了多少字節,JVM內存對齊知道嗎?
代碼
struct {
char a;
int b;
char c;
}
回答:
- char和int分別各佔2、4個字節
- 這幾個變量共佔了8個字節(這是我的回答,是錯誤的)
面試官問我知道JVM內存對齊知道嗎?我第一反應想到的是JVM內存中的對象佈局,
裏面有一塊內存叫對齊填充,意思是JVM對象頭佔用最少8個字節,
實例數據和對象頭+內存填充的內存必須是8字節的整數倍
面試官糾正:三個變量共佔用24個字節,因爲這一塊需要內存對齊,意思是按照內存分配最大的變量分配其
他變量的內存
- 用過什麼數據庫?在MySQL中使用什麼引擎?
- 之前使用的MySQL,在阿里實習轉正期間使用了Oracle
- 在MySQL中使用InnoDB引擎,還有一個叫MyISAM引擎
- 說說InnoDB和MyISAM的區別
- InnoDB支持事務,MyISAM不支持
- InnoDB支持行級鎖,MyISAM不支持,只支持表級鎖,當然InnoDB在where條件不是索引時也會使用表級鎖
- InnoDB傾向於數據的更改,MyISAM傾向於查詢,引用使用索引的不同
- 數據庫事務有幾個特性?分別是?
- 原子性
- 隔離型
- 一致性
- 持久性
- 說說隔離型中隔離級別有哪幾種?分別解決什麼問題
- 未提交讀:會出現髒讀、不可重複讀、幻讀
- 提交讀:避免出現髒讀,但是會出現不可重複讀、幻讀
- 可重複讀:避免不可重複讀,但是會出現幻讀
- serializable:避免出現幻讀
- MySQL如何解決在默認使用可重複讀隔離級別時出現的幻讀
數據庫學習時間很久了,我記得當對某一行數據進行操作時,MySQL默認會對周圍的行數據進行加鎖,
避免出現幻讀
面試官說相對地方了,它的專業名稱叫間隙型鎖
- 看你簡歷有分佈式經歷,使用Dubbo+Zookeeper,你說說分佈式事務
我給大家推薦我自己總結的一篇文章吧,
幾乎回答一樣:https://blog.csdn.net/qq_40910541/article/details/97974388
- 我說到我在項目中排查過分佈式事務空回滾的問題,和面試官一起交流了下事務空回滾的原因,解決方案
- 分佈式事務空回滾概念:分佈式事務一階段提交之後丟失了二階段的提交/回滾操作
- 分佈式事務空回滾導致原因(項目):系統一階段操作由於網絡阻塞導致超時回滾,
一階段恢復之後丟失二階段提交/回滾操作,導致一階段事務懸掛
- 排查問題過程:通過排查線上log日誌發現二階段回滾操作的時間比一階段提交的時間要早1秒,確定是分佈式事務空回滾導致
- 解決方案:1、我在系統中添加了事務懸掛預警,及時發現,及時解決。 2、TCC模塊實現30秒拒絕空回滾
面試官交流也很愉快,說他們部門是60秒拒絕空回滾