一、背景
自己由于某種原因,需要找下份作業,經歷了2周多時間面了20多家(按部門算),其中包括AT, TMDK等大廠,也拿到了一些offer,
整個程序特別緊湊,比較辛苦,加上裸面原因,前期表現的并不好,到后面才嫻熟了一些,
因為這樣連貫的面試車輪戰,很容易就能感受到面試的高頻知識點,對后面的面試就越來越能把握住節奏點,
寫這篇文章的目的,除了自我總結之外,也希望能對后面的年輕人有一些幫助,
二、題目串列:
每家1-3輪不等,題目太多,只能憑印象或當時做的筆記列出,其中高頻的(出現3次及以上)會以紅色標出,
備注:因為時間有限,對每個題目下的答案,僅僅是列出了腦海中的“記憶索引”,僅供參考(水平有限甚至可能還有錯誤),需要自行去學習去總結答案,
1. HashMap資料結構?put, get程序?擴容機制?JDK1.8版本中相比1.7做了哪些優化?容量怎么計算的?
hash表+鏈表+紅黑樹;先計算hashcode,再對&(n-1)計算,最后使用equals判斷;double容量擴容,并進行rehash計算,性能開銷較大;增加了紅黑樹,鏈表插入由頭插該為尾插(為了解決并發場景CPU 100%問題);直接由size屬性回傳
建議:深度分析原始碼,重點關注核心方法
2. ConcurrentHashMap資料結構?如何保證執行緒安全的?相比1.7做了什么優化?
與hashmap結構一致;使用cas保證;使用cas代替segement分段鎖,提升效率
3. 為什么String被設計成不可變的?
設計考慮、效率考慮、安全考慮
4. 限流演算法有哪些?區別是什么?令牌桶如何實作?
漏桶與令牌桶;前者保持勻速,后者能應對突發流量;使用guava的RateLimiter
5. 一致性hash演算法?
已知一個[0, 2^32-1]這樣整數的集合,從小到大按順時針均勻分布,先將機器ip(或hostname等其他唯一資訊)使用某種hash演算法,計算出hash值,
再對2^32取余,定位到環中的某個位置,再對key進行hash計算,對2^32取余,定位到某個位置后,按順時針找到第一個機器的位置,這樣就找到了key與機器的映射關系,
為了解決機器數量過小,會有資料不平衡的問題,可以再建立虛擬節點,如針對172.23.23.23建立172.23.23.23#1, 172.23.23.23#2, 172.23.23.23#3 這樣3個虛擬節點,再做同樣的操作
6. JVM記憶體模型(有些面試官其實只是讓你回答記憶體布局)?各個記憶體區域分別是做什么的?有哪些是共享的?
每個執行緒有獨立的記憶體,互相是隔離的,讀變數時會從主記憶體讀取放到執行緒記憶體中,做完計算后,會“異步”的寫回主記憶體;
虛擬機堆疊用于保存變數參考,此處省略...
建議:JMM這塊知識,有很多細節,涉及happens-before原則,記憶體屏障等很多概念的東西,能理解就去理解下
7. 年輕代,老年代區別?垃圾回收演算法分別是?垃圾回收器有哪些?
前者保存小或生命周期短的物件,后者保存大或生命周期長的物件;前者是復制演算法,后者是標記清除或標記整理演算法;
一共有7個垃圾回收器,注意ParNew和CMS是搭配組合,省略...
8. CMS具體的作業流程?G1與CMS區別?
大致有4個步驟:初始標記->并發標記->重新標記->并發清除,第1和3步會STW(stop the world),這個回收器是以追求回應時間短為目標;
前者有產生浮動垃圾,空間碎片等缺點,后者將堆分為很多個region,不再具有特定的年輕代,老年代,GC時會自適應調整策略,更加智能,也是追求回應時間短為目標,
9. GC Root物件有哪些?
堆疊中變數參考的物件;方法區中靜態屬性、常量應用的物件;JNI中參考的物件
10. 強參考、軟參考?弱應用?虛參考?
被視為存活物件不會被GC;SoftReference,只有在OOM之前才被GC掉;WeakReference,每次GC時都被GC掉;省略..
11. 類加載機制?tomcat為什么打破雙親委派?
默認有3個類加載器,系統、擴展、應用類加載器,使用雙親委派模型, 即每次優先讓父類加載去加載;tomcat可以同時部署多個應用,安全考慮
建議:注意ClassLoader中loadClass,findClass區別
12. 執行緒池有哪些?一般怎么用?這些引數的意義是什么?
默認的有4個,fixed, single, cached, scheduled;不過一般用ThreadPoolExecutor, 包含core, max, alive, blockingQueue, threadFactory, abortPolicy,省略...
建議:這個問題是最最最常問的,建議分析下ThreadPoolExecutor原始碼,洞察內部實作,就不用死記引數之間的聯系了,
13. 執行緒池的執行緒數一般設定多少?
由機器CPU的core數n和并發任務的屬性決定,若任務是CPU密集型,建議設定n+1數量,若任務是IO密集型,建議設定2n數量
14. 執行緒通信的方式?
volatile, wait/notify/notifyAll, condtion#await/singal等
15. Thread有幾種狀態?
NEW,RUNNING, BLOCKED, WAITING, TIMED_WAITING,TERMINATED
建議:這些狀態定義在Thread類本身;需要注意每個狀態是由哪些方法呼叫產生的;另外作業系統下的執行緒本身也有自己的狀態,比JDK定義的更精簡一些,可以自行去對比分析理解
16. sleep與wait區別
前者不會釋放鎖,后者會釋放鎖,兩者都不會占用CPU資源
17. volatile作用?原理?
可見性,有序性(防止重排序);使用記憶體屏障
建議:內部原理實作比較復雜,涉及CPU lock指令,一致性協議等,可自行深入了解
18. ThreadLocal如何實作?
Thread類本身有ThreadLoalMap屬性,所以每個執行緒都有獨立的map資料
19.索引型別?
一般回答角度:普通索引,唯一索引,主鍵索引,聯合索引
(有時會問讓從索引結構角度):hash索引,B+樹索引
20. 為什么使用B+樹?而不是用其它二叉樹或B-樹?B+樹與B-樹區別?
前提知識:資料庫是檔案存盤系統,瓶頸在IO訪問次數上,樹越高,訪問的次數就越多,
B+樹是多叉樹,相同節點要比二叉樹高度低很多,效率會高很多;
相比B-樹,主要有2點優勢,1. 葉子節點有指標相連,做全表掃描時或范圍查詢時會很快,2. 內部節點不存盤資料,只存盤索引值,相同資料頁存盤的節點資訊更多,IO次數也會減少很多,效率就高很多,
21. 聚集索引與非聚集索引區別?
在InnoDB中前者也稱主鍵索引,內部節點存盤主鍵值,葉子節點存盤資料行,后者是內部節點存盤索引值,葉子節點只存盤主鍵值
22. Innodb與Myisam引擎區別?
前者支持事務,后者不支持,前者是聚集索引,后者是非聚集索引
23. 資料庫主從復制程序?binlog日志模式有哪些?
master開啟binlog日志開關,slave節點會有執行緒去讀取binlog,然后寫回到relay log中,再有執行緒去讀取relay log,寫到slave節點中;
statement level記錄操作陳述句, row level記錄操作涉及的所有行資料, mixed level;
24. redolog, undolog區別?
前者是可以恢復被中斷的事務資料,從而繼續提交;后者是可以讓事務回滾到上一個版本,
25. 如果事務未提交,意外宕機?如何恢復?
使用redolog或者undolog恢復,未完成的事務,可以繼續提交,也可以選擇回滾,這基于恢復的策略而定,
26. SQL優化技巧(慢查詢解決方案)
使用explain分析執行計劃報告,避免一些索引使用不當的問題,或有沒有必要建立新的索引,另外可以使用快取,分庫分表解決,
建議:總結出索引使用不當的case,如索引欄位參與計算被寫在sql中等
27. 什么是索引覆寫?
在InnoDB中,select陳述句中select出來的欄位,只包含索引值和主鍵值,不用回表(再次根據主鍵值去查詢主鍵索引,找到資料行)
28. 深層次分頁如何優化?比如 limit 10000, 100這種?
假設主鍵是有序的,先找到100頁的主鍵值a,再根據>a這個條件,再次分頁100,又找到主鍵值b,再根據>b這個條件省略...
建議:這次面試被問到至少3次,前幾年面試真沒遇到過;描述的不精確,可自行去度娘學習
29. spring如何解決回圈依賴?
30. springboot相比spring的優勢?
約定大于配置;自啟動一些組件
31. @Conditional作用
當某個bean的初始化依賴某個class時,可以使用此注解
32. redis常用資料結構?
list, string, hash, set, zset
33. 持久化策略?aof與rdb區別?
有aof和rdb;前者是持久化操作指令,且追加寫入,持久化動作快,但恢復慢,后者是持久化當前全量資料,持久化動作慢,但恢復快,
建議:其實還有混合持久化策略,即aof+rdb;aof與rdb的持久化原理也可去深入了解下,有時可能會被問到
35. 過期key的洗掉策略?
主動洗掉,redis內部有定時去監測key的ttl是否過期;被動洗掉,只有在get時會判斷是否過期
36. redis哨兵模式如何保證高可用?
建議:看有沒有用過吧,可以自行研究
37. 對于redis-cluster,如何保證高可用的?資料是如何存盤的?內部節點如何通信?
多master水平分布,每個master背后有slave做備用節點;redis-cluster,默認會有1.6W多個slot,每個key的hash值對slot總量進行取余,定位到某個slot上,slot是分布在某個master上的;
master-master,master-slave,slave-slave都會依賴同一種二進制協議通信,傳達節點資訊是否正常,存盤的slot號有哪些,都會告訴其它節點,這樣每個master都知道了slot號與master之間的映射關系,
建議:看有沒有用過吧,可以自行研究
39. 事務隔離級別有哪些?mysql默認是哪個?是如何實作可重復讀的?是如何解決幻讀問題的?
讀未提交,讀已提交,可重復讀,可串行化;默認是可重復讀,RR;MVCC為表新增2個虛擬欄位,創建行的版本,洗掉行的版本,每次查詢時都是要小于等于創建版本,所以即使其它事務變更該行,也不會影響當前事務的查詢;使用間隙鎖
建議:這些問題特別特別被經常問到,這塊知識涉及當前讀,快照讀,X鎖, S鎖,間隙鎖,undolog等等,建議系統去深入理解總結
40. 分布式鎖怎么實作的?redis鎖怎么防止被誤釋放?怎么防止死鎖?過期時間怎么設定?怎么續約?
對于redis實作,獲取鎖使用setNx命令,設定key,value,expire;可在value中設定UUID,釋放鎖時,通過lua腳本判斷UUID是否一樣,再通過redis的evl命令執行這個腳本;
通過設定過期時間防止死鎖;預估一個過期時間后,可以有一個“看門狗”的執行緒去檢測鎖的狀態,去自動續約,
建議:這塊需要去系統深入了解下,特別常見,
41. mysql層面樂觀鎖、悲觀鎖實作?
前者加version,在操作sql陳述句中增加version判斷大小的where條件;select ... for update;
42. 什么是cas,有哪些缺點?
compare and set是原子命令;cpu資源開銷,ABA問題等
43. AQS大致機制?
主要有2個核心的屬性:volatile int state,用于標識鎖的狀態;雙向同步佇列,用于保存等待狀態的執行緒,另外使用cas去獲取鎖/釋放鎖
建議:去深入原始碼了解其機制;注意volatile+cas的使用機制,原子類也是這樣實作的
44. Synchroinzed與ReentrantLock區別?
使用方式角度:前者可修飾屬性、方法、代碼塊,后者只能是代碼塊;
其它角度:前者只能是非公平的,后者可支持公平鎖,前者不能回應等待中斷,后者是能回應等待中斷的,
建議:此問題幾乎必問
45. Synchronized是如何實作的? 鎖優化程序?
每個物件都有一個物件鎖,保存在物件頭中;先由偏向鎖,再升級為輕量級鎖,最后是重量級鎖
建議:特別容易被問到,建議去深入學習
46. ReentrantLock怎么實作的?
繼承AbstractQueuedSynchronizer類,去實作,即基于AQS,
45. wait使用時注意哪些?
要被while回圈包住,放在synchroinzed下
46. 場景題匯總:
1) 延時佇列怎么實作的?
建議:參考DelayQueue實作
2) 如何應對未來可能的突發流量?
可從限流、MQ削峰、動態水平擴容等角度去展開講
建議:方案有很多,要實作準備好一種能落地的方案
3) 線上故障排查的思路是什么?
4) 快取穿透如何解決,快取雪崩如何解決?
建議:會有布隆過濾器做防快取穿透的方案;其它可自行去了解學習
5) 你覺得專案的挑戰點/難點/亮點是什么?
建議:要實作準備好,列出個1,2,3,4條出來
6). 動態展示積分排行?zset結構如何實作的?
使用redis的zset結構;跳躍表?
建議:需了解zset大致實作,很容易被追問
7). GC調優經驗?GC線上問題排查?(如記憶體泄漏)
暫無;jmap出快照,下載到本地后,用mat去分析
建議:根據自己經驗+度娘;
8) 如何排查CPU過高問題?
找到行程pid,top -H -p pid(得出占用CPU資源高到低的執行緒資訊),printf %x id(拿到執行緒號去轉16進制),再從jstack出的執行緒堆疊中去找這個執行緒號,最后定位到代碼
9). A執行緒依賴B,B依賴C,怎么實作?
使用wait/notify/notifyAll
10). 待補充...
47. 演算法題匯總:
1) 兩個升序陣列的差集;輸入2個陣列,回傳一個陣列
2) 判斷一棵樹是否是平衡二叉樹;輸入root節點,輸出true/false
3) 已知一個升序的陣列,給特定值a,求在陣列中小于a的最大值(需最優復雜度);輸入陣列和a,輸出陣列中的某個數
4) 給定2個有序的單鏈表,合并成一個有序的單鏈表,且去除重復元素;輸入2個頭結點,輸出新鏈表的頭結點
5) 將數字123422,翻譯成“拾貳萬叁仟肆佰貳拾貳”,即給定任意數字翻譯成漢字;輸入long型數字,輸出字串
6) 說下實作LRU的思路,手寫LRU
建議:優先使用HashMap結構與鏈表結合的方案,參考LinkedHashMap
7) 用兩個堆疊資料結構實作一個佇列的功能,佇列具備入隊、出隊操作功能即可
8) 實作下二分查找
9) 求最大連續子陣列之和
10) 實作下插入排序,并說其是否穩定,時間復雜度是什么
11) 實作一個堆疊(可用JDK中的Stack),要求能額外實作getMin()方法,標識能獲取到此堆疊的最小值
12) 實作層序遍歷
13)待補充...
48 待補充...
三、面試技巧:
上面列出的面試遇到的知識點基本都是大路貨,隨處可見,我們能做的就是盡量去融會貫通,盡量與專案開發實踐中相結合,有自己的心得總結,
對于前3年的,可能對基礎知識考察會多一些;
對于5年左右甚至更多,可能對專案經驗考察更多一些,
在做面試準備時,要根據自身的情況,有側重點的去準備,
具體一些的話,比如簡歷怎么寫,怎么介紹專案,怎么有針對的準備某塊知識等等技巧,后續有空了補上吧,
四、自我總結:
自己這次面試,是臨時抱佛腳,“應試”的心態去準備面試,這樣肯定是很不好的,
希望以后自己能踏踏實實的,平常多總結,做一個real coder.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/164033.html
標籤:Java
上一篇:執行緒池運用不當的一次線上事故
下一篇:redis快取(此文轉載)
