以下總結的面經都是我在秋招的程序中被問到的一些高頻問題,后面附上的一些答案是查閱了相關文章總結而出,也是個人觀點,如有錯誤,歡迎指出!
一 Java基礎
- Java和C語言有什么區別?Java好在哪里?
- 怎么理解Java的跨平臺性,一次編譯到處運行?
- 面向物件和面向程序的區別?
- 如何理解面向物件三大特性:封裝、繼承、多型?
- 類繼承會有什么問題嗎,一般什么情況下才會去用繼承?
- 為什么重寫equals方法還要重寫hashcode方法?
- 深克隆和淺克隆
- 反射相關
- 注解的實作原理
- Lambda運算式的優缺點?
- Stream流式編程的好處?終止方法和延遲方法的區別是?終止方法存在的意義是什么?
二 Java集合
- HashMap底層實作(JDK1.7使用陣列+鏈表;JDK1.8使用陣列+鏈表+紅黑樹)
- HashMap為什么要引進紅黑樹?為什么不用其他的平衡二叉樹之類的?紅黑樹的優勢在哪里?(AVL樹的旋轉比紅黑樹的旋轉更加難以平衡和除錯,需要更高的旋轉次數)
- 鏈表會轉化為紅黑樹的兩個條件是?(①鏈表的長度達到8;②HashMap底層使用的table陣列長度length達到64;如果不滿足后者,將會觸發擴容方法)
- 鏈表長度大于8轉化為紅黑樹,小于6紅黑樹轉化為鏈表;為什么不直接設定成大于8轉化成紅黑樹,小于8轉化成鏈表;(中間有個差值7進行過渡是為了避免鏈表和樹頻繁轉換,如果一個HashMap不停的插入、洗掉元素,鏈表個數在8左右徘徊,就會頻繁的發生樹轉鏈表、鏈表轉樹,效率會很低)
- 把鏈表轉化為紅黑樹的閾值是8,為什么不設定成其他值?(遵循泊松分布,鏈表長度超過8的概率非常小)
- HashMap擴容機制,即resize方法?(JDK 1.7 會重新計算每個元素的哈希值,JDK1.8是通過高位運算(e.hash & oldCap)來確定元素是否需要移動,如果運算結果值為0,那么元素擴容后位置不變,結果值為1表示元素在擴容時位置發生了變化,新的下標位置等于原下標位置 + 原陣列長度)
- HashMap添加元素的步驟(put方法)、計算集合元素個數(size方法)
- HashMap為什么是執行緒不安全的?(同時新增元素、同時擴容導致資料丟失,jdk1.7頭部倒序插入出現死回圈導致CPU占用100%)
- HashMap默認的加載因子是0.75,為什么不設定成1或者0.5(從容量和性能考慮)
- HashMap發生哈希沖突,新節點是插入到鏈表頭部還是鏈表的尾部,頭部倒序插入死回圈是怎么產生的?(jdk1.7采用頭部倒序插入,會導致死回圈;jdk1.8使用尾部正序插入)
- Hashtable怎么控制key value 不能為null?(當呼叫put方法時,首先會判斷value是否為null,為null的話直接拋出空指標例外;對于key,由于Hashtable計算hash值是int hash = key.hashCode();直接取物件的hashcode,key為null就會報空指標例外;而HashMap計算hash值是return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16),key為null則hash值為0)
- ConcurrentHashMap底層采用的結構(分jdk1.7和jdk1.8),jdk1.7和jdk1.8分別采用什么方式實作執行緒安全?(jdk1.7采用分段鎖,也就是為每一個segment加上ReentrantLock鎖;jdk1.8使用的是CAS機制加上synchronized鎖)
- ConcurrentMap中的size方法是如何實作的?多執行緒操作下,如果一個執行緒在查size方法,一個執行緒在執行put方法,底層是如何控制每次計算出來的值是正確的?
- HashSet的底層實作?(基于HashMap來實作的,new 一個 HashSet物件底層實際就是new了一個HashMap,并且使用默認的初始容量16和默認的加載因子0.75;當我們往HashSet里面添加一個元素其實就是往HashMap里面put了一個元素,并且是以key存在的,HashMap的value值都是一樣的,是一個靜態常量PRESENT,原始碼為:
private static final Object PRESENT = new Object();) - BlockingQueue(阻塞佇列)如何實作生產者消費者模型?
- 執行緒安全的List有哪些?(Vector、CopyOnWriteArrayList、還可以使用Collections類的synchronizedList方法將執行緒不安全的List轉為執行緒安全的)
- 為什么ArrayList查詢速度快?(ArrayList底層是基于陣列實作,可以根據元素下標進行查詢,查詢方式為(陣列首地址+元素長度*下標,基于這個位置讀取相應的位元組數就可以了),如果陣列存的是物件,怎么根據下標定位元素所在位置?(物件陣列每個元素存放的是物件的參考,而參考型別如果開啟指標壓縮占用4位元組,不開啟則占用8位元組,所以物件陣列同樣適用上面的公式)
- ArrayList的擴容?(ArrayList底層是基于陣列實作,所以創建ArrayList會給陣列指定一個初始容量,默認值為10,因為必須指明陣列的長度才能給陣列分配空間;由于陣列的特性,ArrayList擴容是創建一個更大的陣列,然后將原來的元素拷貝到更大的陣列中,擴容的核心方法是Arrays.copyOf方法)
- ArrayList和LinkedList的區別,添加一個元素的時間復雜度各是多少,既然ArrayList添加元素效率沒有LinkedList高,為什么我們平時用的比較多的還是ArrayList?
- 一般什么情況下會用ArrayList,什么情況用LinkedList?(如果只是普通的存取元素多用ArrayList,LinkedList一般用作堆疊、佇列)
- 將一個Map集合變成堆疊,如何實作?(我的思路是用TreeMap去實作,key存的是要入堆疊的元素,value存的是可以記錄他們入堆疊的一個先后順序的,例如時間戳,然后重寫Comparator比較器,根據value進行排序,遍歷Map時,先進的后面出)
- Map集合有迭代器嗎?遍歷輸出Map中所有元素有哪些方法?
三 多執行緒和Java鎖
- 執行緒池的三大方法、七大引數、四種拒絕策略(可以順帶談一下阿里巴巴開發手冊對于執行緒池使用的規范)
- 最大執行緒數如何定義?(從CPU密集型和IO密集型考慮)
- 執行緒池的五種狀態(Running、Shutdown、Stop、Tidying、Terminated)
- 執行緒池的任務執行流程、excute方法和 submit方法的區別?
- Synchronized鎖和Lock鎖的區別
- Java執行緒虛假喚醒(執行緒本應該處于wait狀態卻被喚醒了,解決方案是wait方法應該用while回圈包裹,不用if)
- JMM的三種特性(原子性、可見性、有序性)、主記憶體和執行緒作業記憶體的八種互動動作
- volatile如何保證可見性(MESI快取一致性協議)
- volatile如何保證有序性(記憶體屏障——lock前綴指令)
- synchronized和volatile的區別(volatile是一種非鎖機制,這種機制可以避免鎖機制引起的執行緒背景關系切換和調度問題,因此,volatile的執行成本比synchronized更低;volatile只能保證可見性有序性;synchronized可以保證原子性可見性有序性)
- JUC包中的原子類如何保證原子性?(CAS機制和自旋鎖)
- CAS機制,會引發什么問題,如何解決ABA問題?(CAS會導致ABA問題,解決ABA問題是使用版本號機制)
- 悲觀鎖和樂觀鎖的區別,應用?(java中的Synchronized關鍵字和lock鎖使用的都是悲觀鎖;CAS機制是樂觀鎖的一種實作方式)
- 公平鎖和非公平鎖(公平鎖按照先來先服務,不會出現饑餓;非公平鎖會導致饑餓,但是效率更高,默認的鎖都是非公平的)
- 自旋鎖和互斥鎖,自旋鎖的優缺點?(優點:減少背景關系切換和用戶態內核態的切換帶來的開銷;缺點:回圈等待消耗CPU)
- 可重入鎖和不可重入鎖(不可重入鎖容易導致死鎖發生,大多數鎖都是可重入的,例如Synchronized鎖和ReentrantLock)
- JDK1.6 Synchronized鎖升級(偏向鎖—輕量級鎖—重量級鎖)
- Synchronized鎖的底層實作,鎖的是什么,其它執行緒如何判斷該鎖已經被占用了?
- 死鎖產生的四個必要條件以及死鎖的處理策略
四 Mysql
- Myisam和InnoDB存盤引擎的區別?(Myisam不支持外鍵也不支持事務,支持的是表鎖,當執行select操作時,自動給涉及的表加表鎖,當執行增刪改操作,自動給涉及的表加寫鎖;InnoDB支持外鍵也支持事務,支持的是行鎖,當執行select操作時,不加任何鎖,當執行增刪改操作,自動給涉及的行加寫鎖)
- 間隙鎖是什么?行鎖升級為表鎖的情況?
- InnoDB的行鎖有哪些?鎖住的是行還是索引?(Record Lock、Gap Lock、Next-Key Lock;鎖住的是索引,而不是行)
- 為什么可重復讀隔離級別也可以解決幻讀?(通過Next-Key Lock可以消除幻讀)
- 并發事務處理帶來的四種問題和事務的隔離級別(丟失更新、臟讀、不可重復讀、幻讀;讀未提交、讀已提交、可重復讀、串行化)
- 如何理解Mysql默認的事務隔離級別可重復讀?
- 事務的ACID屬性是如何實作的?(原子性通過回滾日志undo log實作;持久性通過重做日志redo log實作;隔離性通過鎖和MVCC實作;而一致性則是通過原子性、隔離性、持久性來實作,只有滿足這三個特性,才能實作事務的一致性)
- 聚簇索引、非聚簇索引、回表查詢、覆寫索引;
- 索引失效的情況?(違反最左前綴法則、范圍查詢右邊的列索引失效、字串不加單引號、對索引列進行運算、頭部模糊匹配、使用不等于!=或者<>)
- explain分析執行計劃、SQL陳述句的優化
- mysql三大范式(1NF即原子性,2NF即消除部分依賴,3NF即消除傳遞依賴)
- mysql索引的底層實作,為什么用B+樹不用B樹?(B+樹IO次數更少、更適合范圍查詢、查詢效率更加穩定)
- 哈希表查找速度不是更快嗎,為什么不直接使用哈希表來做索引的底層資料結構?(哈希表不支持范圍查找)
五 Redis
- Redis五種基本資料型別的使用場景
- 快取穿透、快取擊穿、快取雪崩
- Redis的過期策略和記憶體淘汰機制
- Redis的zset底層資料結構,為什么用跳躍表而不用紅黑樹
六 框架相關
- Spring AOP的實作原理?(基于動態代理模式,如果目標類實作了介面,那么使用基于介面的動態代理,否則使用基于子類/cglib的動態代理)
- Spring AOP 的具體加載步驟?
- AOP和OOP的區別,分別適用什么場景?
- Spring Bean的作用域,Spring Bean的生命周期(Bean的實體化—初始化Bean—使用Bean—Bean的銷毀)
- Spring容器創建物件的兩種時機,各有什么優缺點?(一是Spring容器啟動時創建Bean,二是呼叫getBean方法時創建)
- SpringMVC的執行流程(可以順帶講一下配接器模式)
- Mybatis的一級快取和二級快取?
- Mybatis中#和$的區別?
- Mybatis如何實作批量插入?
- Mybatis的xml檔案中,sql陳述句可以使用直接使用大于號小于號嗎?應該用什么符號代替?
七 設計模式
- 請列舉出在 JDK 中幾個常用的設計模式?
- 什么是設計模式?你是否在你的代碼里面使用過任何設計模式?
- Java 中什么叫單例設計模式?請用 Java 寫出執行緒安全的單例模式
- 在 Java 中,什么叫觀察者設計模式(observer design pattern)?
- 使用工廠模式最主要的好處是什么?在哪里使用?
- 舉一個用 Java 實作的裝飾模式(decorator design pattern)?它是作用于物件層次還是類 層次?
- 在 Java 中,為什么不允許從靜態方法中訪問非靜態變數?
- 設計一個 ATM 機,請說出你的設計思路?
- 在 Java 中,什么時候用多載,什么時候用重寫?
八 網路
-
TCP三次握手和四次揮手的程序,每次發送的包的內容,客戶端和服務端的狀態?
-
TCP三次握手可以攜帶資料嗎?TCP協議運行時階段?
-
為什么是三次握手,可以四次握手或者兩次握手嗎?
-
為什么握手是三次,而揮手要四次?
-
TCP四次揮手為什么需要TIME-WAIT階段等待2MSL,是哪一方有TIME-WAIT階段?(主動釋放釋放連接的那端)
-
TCP的長連接和短連接
-
半連接佇列和全連接佇列,什么是syn flood攻擊,如何應對syn flood攻擊?
-
在瀏覽器中輸入一個網址回車后發生了什么?
-
域名決議程序的遞回查詢和迭代查詢
-
瀏覽器輸入一個網址之后,按照TP/IP參考模型,從應用層到網路層各使用了哪些協議?
(應用層:HTTP、DNS;傳輸層:TCP、UDP;網路層:IP、ICMP、ARP)
-
ICMP協議的兩個應用——Ping和Traceroute
-
IP地址和MAC地址有什么區別?
-
http和https的區別
-
網站為什么要使用cookie和session;cookie和session有什么區別?
-
get請求和post請求的區別?
-
TCP和UDP的區別以及各自的應用場景?
-
epoll和select的區別?
九 JVM
-
JVM記憶體模型(程式計數器、虛擬機堆疊、本地方法堆疊、堆、方法區)
-
JDK1.8做了哪些變化?(JDK1.7已經將原本位于永久代的字串常量池移到堆中了,但是永久代的概念還存在,JDK1.8才徹底廢除永久代,進而用元空間代替)
-
永久代和元空間,JDK1.8為什么要使用元空間代替永久代?
-
元空間溢位?(元空間不屬于Java虛擬機,使用的是本地記憶體,存放的是類及方法的一些資訊,動態加載類或者頻繁加載類資訊,但是沒有及時卸載,會導致元空間溢位)
-
物件創建的兩種方式(指標碰撞、空閑串列)、物件訪問定位的兩種方式(使用句柄、直接指標)
-
堆疊上分配與逃逸分析(JVM層面進行java性能優化的技巧)
-
判斷物件是否存活的兩種方式,參考計數法的缺點?(參考計數法、可達性分析法)
-
關于Object類的finalize()方法(jvm自動執行,無需手動呼叫,只能執行一次).
-
java的四種參考(強參考、軟參考、弱參考、虛參考)
-
三種垃圾回收演算法,各自的優缺點(標記-清除法、標記-復制法、標記-整理法)
-
Minor GC 和 Full GC 的區別,觸發條件,以及空間分配擔保策略?
-
記憶體溢位和記憶體泄露(記憶體泄露的堆積會導致記憶體溢位)
-
JVM引數調優(-Xms、-Xmx、-Xss、-XX:NewRatio、-XX:SurvivorRatio、-XX:+PrintGCDetails、-HeapDumpOnOutOfMemory)
-
發生OOM如何解決(首先嘗試通過JVM引數調優擴大堆記憶體空間;再者dump出堆記憶體存盤快照,使用JProfile工具進行分析)
-
垃圾收集器(CMS問的居多,另外,如果談及發生gc會給用戶帶來什么不好的體驗,可以談談Stop the World)
-
類加載機制的程序,準備階段做了哪些作業?(準備階段會給類的靜態變數分配記憶體(方法區)并賦初值,如果類的靜態變數被final修飾,那么初始化的值就不是零值,而是宣告的值)
-
類的雙親委派模型定義,雙親委派模型的好處?如何破壞類的雙親委派模型?
十 作業系統
- linux的僵尸行程和孤兒行程的區別,如何清理僵尸行程?(kill僵尸行程的父行程)
- 如何查看僵尸行程資訊?如何統計僵尸行程數量?(ps - ef | grep defunct;ps -ef | grep defunct | wc - l)
- 并發和并行的區別?
- 行程和執行緒的區別?
- 行程通信的方式有哪些?(管道、訊息佇列、共享記憶體、信號量、套接字Socket)
都整理在網盤了需要的可以點擊這里,暗號博客園!


轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/242264.html
標籤:其他
