就目前的一線企業面試模式來講,尤其是一面與二面都涉及到很深的Java基礎功底及知識面,在面試前積極的準備面試,復習整個 Java 知識體系將變得非常重要,可以很負責任的說一句,復習準備的是否充分,將直接影響你入職的成功率,但很多朋友卻苦于沒有合適的復習資料來回顧整個 Java 知識體系,或者有的小伙伴可能都不知道該從哪里開始復習,
我在網上搜集整理的這份Java面試核心筆記資料,不論是從整個 Java 知識體系,還是從面試的角度來看,都是一份含技術量很高的資料,同時還分享一份我自己整理Java工程師高頻面試檔案,其中包括了包含集合,JVM,多執行緒并發、Spring,負載均衡,微服務,Redis,Dubbo,設計模式,資料結構,分布式等!【點擊這里,暗號博客園】免費獲取!
Java基礎面試題
1. 何為編程
編程就是讓計算機為解決某個問題而使用某種程式設計語言撰寫程式代碼,并最終得到結果的過
程,
為了使計算機能夠理解人的意圖,人類就必須要將需解決的問題的思路、方法、和手段通過計算機
能夠理解的形式告訴計算機,使得計算機能夠根據人的指令一步一步去作業,完成某種特定的任
務,這種人和計算機之間交流的程序就是編程,
2. 什么是Java
Java是一門面向物件編程語言,不僅吸收了C++語言的各種優點,還摒棄了C++里難以理解的多繼
承、指標等概念,因此Java語言具有功能強大和簡單易用兩個特征,Java語言作為靜態面向物件編
程語言的代表,極好地實作了面向物件理論,允許程式員以優雅的思維方式進行復雜的編程 ,
3. jdk1.5之后的三大版本
Java SE(J2SE,Java 2 Platform Standard Edition,標準版)
Java SE 以前稱為 J2SE,它允許開發和部署在桌面、服務器、嵌入式環境和實時環境中使用的 Java
應用程式,Java SE 包含了支持 Java Web 服務開發的類,并為Java EE和Java ME提供基礎,
Java EE(J2EE,Java 2 Platform Enterprise Edition,企業版)
Java EE 以前稱為 J2EE,企業版本幫助開發和部署可移植、健壯、可伸縮且安全的服務器端Java 應
用程式,Java EE 是在 Java SE 的基礎上構建的,它提供 Web 服務、組件模型、管理和通信 API,
可以用來實作企業級的面向服務體系結構(service-oriented architecture,SOA)和 Web2.0應
用程式,2018年2月,Eclipse 宣布正式將 JavaEE 更名為 JakartaEE
Java ME(J2ME,Java 2 Platform Micro Edition,微型版)
Java ME 以前稱為 J2ME,Java ME 為在移動設備和嵌入式設備(比如手機、PDA、電視機頂盒和
列印機)上運行的應用程式提供一個健壯且靈活的環境,Java ME 包括靈活的用戶界面、健壯的安
全模型、許多內置的網路協議以及對可以動態下載的連網和離線應用程式的豐富支持,基于 Java
ME 規范的應用程式只需撰寫一次,就可以用于許多設備,而且可以利用每個設備的本機功能,
4. Jdk和Jre和JVM的區別
看Java官方的圖片,Jdk中包括了Jre,Jre中包括了JVM
JDK :Jdk還包括了一些Jre之外的東西 ,就是這些東西幫我們編譯Java代碼的, 還有就是監控Jvm
的一些工具 Java Development Kit是提供給Java開發人員使用的,其中包含了Java的開發工具,也
包括了JRE,所以安裝了JDK,就無需再單獨安裝JRE了,其中的開發工具:編譯工具(javac.exe),
打包工具(jar.exe)等
JRE :Jre大部分都是 C 和 C++ 語言撰寫的,他是我們在編譯java時所需要的基礎的類別庫 Java
Runtime Environment包括Java虛擬機和Java程式所需的核心類別庫等,核心類別庫主要是java.lang
包:包含了運行Java程式必不可少的系統類,如基本資料型別、基本數學函式、字串處理、線
程、例外處理類等,系統預設加載這個包
如果想要運行一個開發好的Java程式,計算機中只需要安裝JRE即可,
Jvm:在倒數第二層 由他可以在(最后一層的)各種平臺上運行 Java Virtual Machine是Java虛擬
機,Java程式需要運行在虛擬機上,不同的平臺有自己的虛擬機,因此Java語言可以實作跨平臺,
5. 什么是跨平臺性?原理是什么
所謂跨平臺性,是指java語言撰寫的程式,一次編譯后,可以在多個系統平臺上運行,
實作原理:Java程式是通過java虛擬機在系統平臺上運行的,只要該系統可以安裝相應的java虛擬
機,該系統就可以運行java程式,
6. Java語言有哪些特點
簡單易學(Java語言的語法與C語言和C++語言很接近)
面向物件(封裝,繼承,多型)
平臺無關性(Java虛擬機實作平臺無關性)
支持網路編程并且很方便(Java語言誕生本身就是為簡化網路編程設計的)
支持多執行緒(多執行緒機制使應用程式在同一時間并行執行多項任)
健壯性(Java語言的強型別機制、例外處理、垃圾的自動收集等)
安全性好
7. 什么是位元組碼?采用位元組碼的最大好處是什么
位元組碼:Java源代碼經過虛擬機編譯器編譯后產生的檔案(即擴展為.class的檔案),它不面向任
何特定的處理器,只面向虛擬機,
采用位元組碼的好處:
Java語言通過位元組碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留
了解釋型語言可移植的特點,所以Java程式運行時比較高效,而且,由于位元組碼并不專對一種特定
的機器,因此,Java程式無須重新編譯便可在多種不同的計算機上運行,
先看下java中的編譯器和解釋器:
Java中引入了虛擬機的概念,即在機器和編譯程式之間加入了一層抽象的虛擬機器,這臺虛擬的機
器在任何平臺上都提供給編譯程式一個的共同的介面,編譯程式只需要面向虛擬機,生成虛擬機能
夠理解的代碼,然后由解釋器來將虛擬機代碼轉換為特定系統的機器碼執行,在Java中,這種供虛
擬機理解的代碼叫做位元組碼(即擴展為.class的檔案),它不面向任何特定的處理器,只面向虛擬
機,每一種平臺的解釋器是不同的,但是實作的虛擬機是相同的,Java源程式經過編譯器編譯后變
成位元組碼,位元組碼由虛擬機解釋執行,虛擬機將每一條要執行的位元組碼送給解釋器,解釋器將其翻
譯成特定機器上的機器碼,然后在特定的機器上運行,這就是上面提到的Java的特點的編譯與解釋
并存的解釋,
Java源代碼---->編譯器---->jvm可執行的Java位元組碼(即虛擬指令)---->jvm---->jvm中解釋器----->機
器可執行的二進制機器碼---->程式運行,
8. 什么是Java程式的主類?應用程式和小程式的主類有何不同?
一個程式中可以有多個類,但只能有一個類是主類,在Java應用程式中,這個主類是指包含main()
方法的類,而在Java小程式中,這個主類是一個繼承自系統類JApplet或Applet的子類,應用程式
的主類不一定要求是public類,但小程式的主類要求必須是public類,主類是Java程式執行的入口
點,
9. Java應用程式與小程式之間有那些差別?
簡單說應用程式是從主執行緒啟動(也就是main()方法),applet小程式沒有main方法,主要是嵌在瀏
覽器頁面上運行(呼叫init()執行緒或者run()來啟動),嵌入瀏覽器這點跟flash的小游戲類似,
10. Java和C++的區別
我知道很多人沒學過C++,但是面試官就是沒事喜歡拿咱們Java和C++比呀!沒辦法!!!就算沒學過C++,也要
記下來!
都是面向物件的語言,都支持封裝、繼承和多型
Java不提供指標來直接訪問記憶體,程式記憶體更加安全
Java的類是單繼承的,C++支持多重繼承;雖然Java的類不可以多繼承,但是介面可以多繼承,
Java有自動記憶體管理機制,不需要程式員手動釋放無用記憶體
11. Oracle JDK 和 OpenJDK 的對比
- Oracle JDK版本將每三年發布一次,而OpenJDK版本每三個月發布一次;
- OpenJDK 是一個參考模型并且是完全開源的,而Oracle JDK是OpenJDK的一個實作,并不是完全
開源的; - Oracle JDK 比 OpenJDK 更穩定,OpenJDK和Oracle JDK的代碼幾乎相同,但Oracle JDK有更多的
類和一些錯誤修復,因此,如果您想開發企業/商業軟體,我建議您選擇Oracle JDK,因為它經過
了徹底的測驗和穩定,某些情況下,有些人提到在使用OpenJDK 可能會遇到了許多應用程式崩潰
的問題,但是,只需切換到Oracle JDK就可以解決問題; - 在回應性和JVM性能方面,Oracle JDK與OpenJDK相比提供了更好的性能;
- Oracle JDK不會為即將發布的版本提供長期支持,用戶每次都必須通過更新到最新版本獲得支持來
獲取最新版本; - Oracle JDK根據二進制代碼許可協議獲得許可,而OpenJDK根據GPL v2許可獲得許可,
基礎語法
資料型別
12. Java有哪些資料型別
定義:Java語言是強型別語言,對于每一種資料都定義了明確的具體的資料型別,在記憶體中分配了不同
大小的記憶體空間,
分類
基本資料型別
數值型
整數型別(byte,short,int,long)
浮點型別(float,double)
字符型(char)
布爾型(boolean)
參考資料型別
類(class)
介面(interface)
陣列([])
JVM面試題
1.什么情況下會發生堆疊記憶體溢位,
思路: 描述堆疊定義,再描述為什么會溢位,再說明一下相關配置引數,OK的話可以給面試官手寫是一
個堆疊溢位的demo,
我的答案:
堆疊是執行緒私有的,他的生命周期與執行緒相同,每個方法在執行的時候都會創建一個堆疊幀,用來存盤
區域變數表,運算元堆疊,動態鏈接,方法出口等資訊,區域變數表又包含基本資料型別,物件參考
型別
如果執行緒請求的堆疊深度大于虛擬機所允許的最大深度,將拋出StackOverflowError例外,方法遞
歸呼叫產生這種結果,
如果Java虛擬機堆疊可以動態擴展,并且擴展的動作已經嘗試過,但是無法申請到足夠的記憶體去完成
擴展,或者在新建立執行緒的時候沒有足夠的記憶體去創建對應的虛擬機堆疊,那么Java虛擬機將拋出一
個OutOfMemory 例外,(執行緒啟動過多)
引數 -Xss 去調整JVM堆疊的大小
2.詳解JVM記憶體模型
思路: 給面試官畫一下JVM記憶體模型圖,并描述每個模塊的定義,作用,以及可能會存在的問題,如堆疊
溢位等,
我的答案:JVM記憶體結構
程式計數器:當前執行緒所執行的位元組碼的行號指示器,用于記錄正在執行的虛擬機位元組指令地址,執行緒
私有,
Java虛擬堆疊:存放基本資料型別、物件的參考、方法出口等,執行緒私有,
Native方法堆疊:和虛擬堆疊相似,只不過它服務于Native方法,執行緒私有,
Java堆:java記憶體最大的一塊,所有物件實體、陣列都存放在java堆,GC回收的地方,執行緒共享,
方法區:存放已被加載的類資訊、常量、靜態變數、即時編譯器編譯后的代碼資料等,(即永久帶),
回收目標主要是常量池的回收和型別的卸載,各執行緒共享
3.JVM記憶體為什么要分成新生代,老年代,持久代,新生代中為什么
要分為Eden和Survivor,
思路: 先講一下JAVA堆,新生代的劃分,再談談它們之間的轉化,相互之間一些引數的配置(如: –
XX:NewRatio,–XX:SurvivorRatio等),再解釋為什么要這樣劃分,最好加一點自己的理解,
我的答案:
1)共享記憶體區劃分
共享記憶體區 = 持久帶 + 堆
持久帶 = 方法區 + 其他
Java堆 = 老年代 + 新生代
新生代 = Eden + S0 + S1
2)一些引數的配置
默認的,新生代 ( Young ) 與老年代 ( Old ) 的比例的值為 1:2 ,可以通過引數 –XX:NewRatio 配
置,
默認的,Edem : from : to = 8 : 1 : 1 ( 可以通過引數 –XX:SurvivorRatio 來設定)
Survivor區中的物件被復制次數為15(對應虛擬機引數 -XX:+MaxTenuringThreshold)
3)為什么要分為Eden和Survivor?為什么要設定兩個Survivor區?
如果沒有Survivor,Eden區每進行一次Minor GC,存活的物件就會被送到老年代,老年代很快被
填滿,觸發Major GC.老年代的記憶體空間遠大于新生代,進行一次Full GC消耗的時間比Minor GC
長得多,所以需要分為Eden和Survivor,
Survivor的存在意義,就是減少被送到老年代的物件,進而減少Full GC的發生,Survivor的預篩選
保證,只有經歷16次Minor GC還能在新生代中存活的物件,才會被送到老年代,
設定兩個Survivor區最大的好處就是解決了碎片化,剛剛新建的物件在Eden中,經歷一次Minor
GC,Eden中的存活物件就會被移動到第一塊survivor space S0,Eden被清空;等Eden區再滿
了,就再觸發一次Minor GC,Eden和S0中的存活物件又會被復制送入第二塊survivor space
S1(這個程序非常重要,因為這種復制演算法保證了S1中來自S0和Eden兩部分的存活物件占用連續
的記憶體空間,避免了碎片化的發生)
4. JVM中一次完整的GC流程是怎樣的,物件如何晉升到老年代
思路: 先描述一下Java堆記憶體劃分,再解釋Minor GC,Major GC,full GC,描述它們之間轉化流程,
我的答案:
Java堆 = 老年代 + 新生代
新生代 = Eden + S0 + S1
當 Eden 區的空間滿了, Java虛擬機會觸發一次 Minor GC,以收集新生代的垃圾,存活下來的對
象,則會轉移到 Survivor區,
大物件(需要大量連續記憶體空間的Java物件,如那種很長的字串)直接進入老年態;
如果物件在Eden出生,并經過第一次Minor GC后仍然存活,并且被Survivor容納的話,年齡設為
1,每熬過一次Minor GC,年齡+1,若年齡超過一定限制(15),則被晉升到老年態,即長期存
活的物件進入老年態,
老年代滿了而無法容納更多的物件,Minor GC 之后通常就會進行Full GC,Full GC 清理整個記憶體
堆 – 包括年輕代和年老代,
Major GC 發生在老年代的GC,清理老年區,經常會伴隨至少一次Minor GC,比Minor GC慢10
倍以上,
5.你知道哪幾種垃圾收集器,各自的優缺點,重點講下cms和G1,包括原理,流程,優缺點,
思路: 一定要記住典型的垃圾收集器,尤其cms和G1,它們的原理與區別,涉及的垃圾回收演算法,
我的答案:
1)幾種垃圾收集器:
Serial收集器: 單執行緒的收集器,收集垃圾時,必須stop the world,使用復制演算法,
ParNew收集器: Serial收集器的多執行緒版本,也需要stop the world,復制演算法,
Parallel Scavenge收集器: 新生代收集器,復制演算法的收集器,并發的多執行緒收集器,目標是達
到一個可控的吞吐量,如果虛擬機總共運行100分鐘,其中垃圾花掉1分鐘,吞吐量就是99%,
Serial Old收集器: 是Serial收集器的老年代版本,單執行緒收集器,使用標記整理演算法,
Parallel Old收集器: 是Parallel Scavenge收集器的老年代版本,使用多執行緒,標記-整理演算法,
CMS(Concurrent Mark Sweep) 收集器: 是一種以獲得最短回收停頓時間為目標的收集器,標
記清除演算法,運作程序:初始標記,并發標記,重新標記,并發清除,收集結束會產生大量空間碎
片,
G1收集器: 標記整理演算法實作,運作流程主要包括以下:初始標記,并發標記,最終標記,篩選
標記,不會產生空間碎片,可以精確地控制停頓,
2)CMS收集器和G1收集器的區別:
CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用;
G1收集器收集范圍是老年代和新生代,不需要結合其他收集器使用;
CMS收集器以最小的停頓時間為目標的收集器;
G1收集器可預測垃圾回收的停頓時間
CMS收集器是使用“標記-清除”演算法進行的垃圾回收,容易產生記憶體碎片
G1收集器使用的是“標記-整理”演算法,進行了空間整合,降低了記憶體空間碎片,
6.JVM記憶體模型的相關知識了解多少,比如重排序,記憶體屏障,
happen-before,主記憶體,作業記憶體,
思路: 先畫出Java記憶體模型圖,結合例子volatile ,說明什么是重排序,記憶體屏障,最好能給面試官寫
以下demo說明,
我的答案:
1)Java記憶體模型圖:
Java記憶體模型規定了所有的變數都存盤在主記憶體中,每條執行緒還有自己的作業記憶體,執行緒的作業記憶體中保存了該執行緒中是用到的變數的主記憶體副本拷貝,執行緒對變數的所有操作都必須在作業記憶體中進行,而不能直接讀寫主記憶體,不同的執行緒之間也無法直接訪問對方作業記憶體中的變數,執行緒間變數的傳遞均需 要自己的作業記憶體和主存之間進行資料同步進行,
2)指令重排序,
在這里,先看一段代碼
運行結果可能為(1,0)、(0,1)或(1,1),也可能是(0,0),因為,在實際運行時,代碼指令可能并不是嚴格按
照代碼陳述句順序執行的,大多數現代微處理器都會采用將指令亂序執行(out-of-order execution,簡
稱OoOE或OOE)的方法,在條件允許的情況下,直接運行當前有能力立即執行的后續指令,避開獲取
下一條指令所需資料時造成的等待3,通過亂序執行的技術,處理器可以大大提高執行效率,而這就是
指令重排,
3)記憶體屏障
記憶體屏障,也叫記憶體柵欄,是一種CPU指令,用于控制特定條件下的重排序和記憶體可見性問題,
LoadLoad屏障:對于這樣的陳述句Load1; LoadLoad; Load2,在Load2及后續讀取操作要讀取的
資料被訪問前,保證Load1要讀取的資料被讀取完畢,
StoreStore屏障:對于這樣的陳述句Store1; StoreStore; Store2,在Store2及后續寫入操作執行
前,保證Store1的寫入操作對其它處理器可見,
LoadStore屏障:對于這樣的陳述句Load1; LoadStore; Store2,在Store2及后續寫入操作被刷出
前,保證Load1要讀取的資料被讀取完畢,
StoreLoad屏障:對于這樣的陳述句Store1; StoreLoad; Load2,在Load2及后續所有讀取操作執行
前,保證Store1的寫入對所有處理器可見,它的開銷是四種屏障中最大的, 在大多數處理器的實
現中,這個屏障是個萬能屏障,兼具其它三種記憶體屏障的功能,
4)happen-before原則
單執行緒happen-before原則:在同一個執行緒中,書寫在前面的操作happen-before后面的操作,
鎖的happen-before原則:同一個鎖的unlock操作happen-before此鎖的lock操作,
volatile的happen-before原則:對一個volatile變數的寫操作happen-before對此變數的任意操
作(當然也包括寫操作了),
happen-before的傳遞性原則:如果A操作 happen-before B操作,B操作happen-before C操
作,那么A操作happen-before C操作,
執行緒啟動的happen-before原則:同一個執行緒的start方法happen-before此執行緒的其它方法,
執行緒中斷的happen-before原則 :對執行緒interrupt方法的呼叫happen-before被中斷執行緒的檢測
到中斷發送的代碼,
執行緒終結的happen-before原則: 執行緒中的所有操作都happen-before執行緒的終止檢測,
物件創建的happen-before原則: 一個物件的初始化完成先于他的finalize方法呼叫,
Netty面試題
最流行的 NIO 框架,由 JBOSS 提供的,整合了FTP,SMTP,HTTP協議
- API 簡單
- 成熟穩定
- 社區活躍·
- 經過大規模驗證(互聯網、大資料、網路游戲、電信通信)
Elasticsearch、Hadoop 子專案 avro專案、阿里開源框架 Dubbo、使用 Netty
BIO
優點:模型簡單,編碼簡單缺點:性能瓶頸,請求數和執行緒數 N:N 關系高并發情況下 ,CPU 切換執行緒上
下文損耗大案例:Tomcat 7之前,都是 BIO,7 之后是 NIO改進:偽 NIO,使用執行緒池去處理邏輯
IO 模式
同步阻塞:丟衣服->等洗衣機洗完->再去晾衣服同步非阻塞:丟衣服->去做其他事情,定時去看衣服是
否洗完->洗完后自己去晾衣服異步非阻塞:丟衣服-> 去做其他事情不管了,衣服洗好會自動晾好,并且
通知你晾好了
2. 五種 I/O 模型
五種 I/O 模型:阻塞 IO、非阻塞 IO、多路復用 IO、信號驅動 IO、異步 IO,前 4 種是同步 IO,在內核
資料 copy 到用戶空間時是阻塞的
3. 阻塞 IO
4. 非阻塞 IO
5. IO 多路復用
核心:可以同時處理多個 connection,呼叫系統 select 和 recvfrom函式每一個socket 設定為 non- blocking 阻塞是被 select 這個函式 block 而不是 socket阻塞缺點:連接數不高的情況下,性能不一定 比 多執行緒+阻塞 IO 好(多呼叫一個select 函式)
信號驅動
異步 IO
采用 Future-Listener機制
IO 操作分為 2 步:
- 發起 IO 請求,等待資料準備
- 實際的 IO 操作,將資料從內核拷貝到行程中
阻塞 IO、非阻塞 IO 區別在于發起 IO 請求是否被阻塞
同步 IO、異步 IO 在于實際的 IO 讀寫是否阻塞請求行程
阻塞非阻塞是執行緒的狀態
同步和異步是訊息的通知機制
同步需要主動讀寫資料,異步不需要主動讀寫資料
同步 IO 和異步 IO 是針對用戶應用程式和內核的互動
3.IO 多路復用
I/O 是指網路 I /O ,多路指多個 TCP 連接,復用指一個或幾個執行緒,簡單來說:就是使用一個或者幾個
執行緒處理多個 TCP 連接,最大優勢是減少系統開銷,不必創建過多的執行緒行程,也不必維護這些執行緒進
程
select
檔案描述符 writefds、readdfs、exceptfds30w個連接會阻塞住,等資料可讀、可寫、出例外、或者超
時回傳select 函式正常回傳后,通過遍歷 fdset整個陣列才能發現哪些句柄發生了事件,來找到就緒的
描述符fd,然后進行對應的 IO操作,幾乎在所有的平臺上支持,跨平臺支持性好缺點: - select采用輪詢的方式掃描檔案描述符,全部掃描,隨著檔案描述符 FD 數量增多而性能下降,
- 每次呼叫 slect (),需要把 fd集合從用戶態拷貝到內核態,并進行遍歷(訊息傳遞都是內核到用戶
空間) - 最大缺陷就是單個行程打開的FD 有限制,默認是 1024
poll
基本流程和 select差不多,處理多個描述符也是輪詢,根據描述符的狀態進行處理,一樣需要把fd集合
從用戶態拷貝到內核態,并進行遍歷,區別是poll 沒有最大檔案描述符限制(使用鏈表方式存盤fd)
epoll
沒有描述符限制,用戶態拷貝到內核態只需要一次使用事件通知,通過epoll_ctl注冊fd,一旦該fd 就緒,
內核就采用callback機制激活對應的fd優點: - 沒有fd限制,所支持的 FD 上限是作業系統的最大檔案句柄數(65535),1G 記憶體大概支持 10W
句柄,支持百萬連接的話,16G 記憶體就可以搞定 - 效率高,使用回呼通知而不是輪詢方式,不會隨著 FD 數目增加效率下降
- 通過 callback 機制通知,內核和用戶空間 mmap 同一塊記憶體實作
缺點:
編程模型比 select / poll 復雜
linux內核核心函式 - epoll_create() 系統啟動時,會向linux內核申請一個檔案系統,b+樹,回傳epoll 物件,也是一個
fd - epoll_ctl() 操作epoll物件,在這個物件里面修改添加洗掉對應的鏈接fd,系結一個callback函式
- epoll_wait() 判斷并完成對應的 IO 操作
例子:100W 個連接,1W 個活躍,在 select ,poll,epoll中怎么樣表現
select :不修改宏定義,需要 1000 個行程才能支持 100W 連接
poll:100W連接,遍歷都回應不過來,還有空間的拷貝消耗大量的資源
epoll: 不用遍歷fd,不用內核空間和用戶空間資料的拷貝
如果 100W 個連接中,95W 活躍,則 poll 和 epoll差不多
4.Java的i/o - jdk1.4之前是采用同步阻塞模型(BIO)
大型服務一般采用 C/C++,因為可以直接作業系統提供的異步 IO(AIO) - jdk1.4之后推出NIO,支持非阻塞 IO,jdk1.7 升級推出 NIO2.0,提供了AIO 功能,支持檔案和網路
套接字的異步 IO
5.Netty 執行緒模型和 Reactor 模式
Reactor模式(反應器設計模式),是一種基于事件驅動的設計模式,在事件驅動的應用中,將一個或
者多個客戶的請求進行分離和調度,在事件驅動的應用中,同步地,有序地處理接受多個服務請求,屬
于同步非阻塞 IO優點: - 回應快,不會因為單個同步而阻塞,雖然 reactor本身是同步的
- 編程相對簡單,最大程度避免復雜的多執行緒以及同步問題,避免了多執行緒、行程切換開銷
- 可擴展性,可以方便的通過 reactor實體個數充分利用 CPU 資源
缺點: - 相對復雜,不易于除錯
- reactor模式需要系統底層的支持,比如java中的selector支持,作業系統select系統呼叫支持
Reactor 單執行緒模型 - 作為 NIO 服務器,接受客戶端 TCP 連接,作為 NIO 客戶端,向服務端發起 TCP 連接
- 服務端讀請求資料并回應,客戶端寫請求并讀取回應
場景:
對應小業務則適合,編碼簡單,對于高負載,高并發不合適,一個 NIO 執行緒處理太多請求,負載
很高,并且回應變慢,導致大量請求超時,萬一執行緒掛了,則不可用
Reactor 多執行緒模型
一個 Acceptor執行緒,一組 NIO 執行緒,一般是使用自帶執行緒池,包含一個任務佇列和多個可用執行緒場
景:可滿足大多數場景,當Acceptor需要做負責操作的時候,比如認證等耗時操作 ,在高并發情況下
也會有性能問題
Reactor 主從執行緒模型
Acceptor不在是一個執行緒,而是一組 NIO 執行緒,IO 執行緒也是一組 NIO 執行緒,這樣就是 2 個執行緒池去處
理接入和處理 IO場景:滿足目前大部分場景,也是 Netty推薦使用的執行緒模型BossGroup 處理連接的
WorkGroup 處理業務的
Netty 使用 NIO 而不是 AIO
在 linux系統上,AIO 的底層實作仍然使用 epoll,與 NIO 相同,因此在性能上沒有明顯的優勢Netty 整
體架構是 reactor 模型,采用 epoll機制,IO 多路復用,同步非阻塞模型Netty是基于 Java NIO 類別庫實
現的異步通訊框架特點: 異步非阻塞,基于事件驅動,性能高,高可靠性,高可定制性,
6.Echo服務
回顯服務,用于除錯和檢測的服務
MySQL面試題
1. 唯一索引比普通索引快嗎, 為什么
唯一索引不一定比普通索引快, 還可能慢.
- 查詢時, 在未使用 limit 1 的情況下, 在匹配到一條資料后, 唯一索引即回傳, 普通索引會繼續匹配
下一條資料, 發現不匹配后回傳. 如此看來唯一索引少了一次匹配, 但實際上這個消耗微乎其微. - 更新時, 這個情況就比較復雜了. 普通索引將記錄放到 change buffer 中陳述句就執行完畢了. 而對
唯一索引而言, 它必須要校驗唯一性, 因此, 必須將資料頁讀入記憶體確定沒有沖突, 然后才能繼續操
作. 對于寫多讀少的情況, 普通索引利用 change buffer 有效減少了對磁盤的訪問次數, 因此普通
索引性能要高于唯一索引.
2. MySQL由哪些部分組成, 分別用來做什么
Server
連接器: 管理連接, 權限驗證.
分析器: 詞法分析, 語法分析.
優化器: 執行計劃生成, 索引的選擇.
執行器: 操作存盤引擎, 回傳執行結果.
2. 存盤引擎: 存盤資料, 提供讀寫介面.
3. MySQL查詢快取有什么弊端, 應該什么情況下使用, 8.0
版本對查詢快取有什么變更.
查詢快取可能會失效非常頻繁, 對于一個表, 只要有更新, 該表的全部查詢快取都會被清空. 因此對
于頻繁更新的表來說, 查詢快取不一定能起到正面效果.
對于讀遠多于寫的表可以考慮使用查詢快取.
8.0版本的查詢快取功能被刪了 ( ̄. ̄).
4. MyISAM和InnoDB的區別有哪些**
InnoDB支持事務, MyISAM不支持.
InnoDB支持行級鎖, MyISAM支持表級鎖.
InnoDB支持多版本并發控制(MVVC), MyISAM不支持.
InnoDB支持外鍵, MyISAM不支持.
MyISAM支持全文索引, InnoDB部分版本不支持(但可以使用Sphinx插件)
5. MySQL怎么恢復半個月前的資料
通過整庫備份+binlog進行恢復. 前提是要有定期整庫備份且保存了binlog日志.
6. MySQL事務的隔離級別, 分別有什么特點
- 讀未提交(RU): 一個事務還沒提交時, 它做的變更就能被別的事務看到.
- 讀提交(RC): 一個事務提交之后, 它做的變更才會被其他事務看到.
- 可重復讀(RR): 一個事務執行程序中看到的資料, 總是跟這個事務在啟動時看到的資料是一致的. 當
然在可重復讀隔離級別下, 未提交變更對其他事務也是不可見的. - 串行化(S): 對于同一行記錄, 讀寫都會加鎖. 當出現讀寫鎖沖突的時候, 后訪問的事務必須等前一個
事務執行完成才能繼續執行.
7. 做過哪些MySQL索引相關優化
盡量使用主鍵查詢: 聚簇索引上存盤了全部資料, 相比普通索引查詢, 減少了回表的消耗.
MySQL5.6之后引入了索引下推優化, 通過適當的使用聯合索引, 減少回表判斷的消耗.
若頻繁查詢某一列資料, 可以考慮利用覆寫索引避免回表.
聯合索引將高頻欄位放在最左邊.
8. 簡要說一下資料庫范式
第一范式: 屬性不可再分.
第二范式: 在一范式的基礎上, 要求資料庫表中的每個實體或行必須可以被惟一地區分. 通常需要為
表加上一個列, 以存盤各個實體的惟一標識. 這個惟一屬性列被稱為主關鍵字或主鍵.
第三范式: 在二范式的基礎上, 要求一個資料庫表中不包含已在其它表中已包含的非主關鍵字資訊.
所以第三范式具有如下特征:1). 每一列只有一個值. 2). 每一行都能區分. 3). 每一個表都不包含其
他表已經包含的非主關鍵字資訊.
9. 一千萬條資料的表, 如何分頁查詢
資料量過大的情況下, limit offset 分頁會由于掃描資料太多而越往后查詢越慢. 可以配合當前頁最后
一條ID進行查詢, SELECT * FROM T WHERE id > #{ID} LIMIT #{LIMIT} . 當然, 這種情況下ID必須
是有序的, 這也是有序ID的好處之一.
10. 訂單表資料量越來越大導致查詢緩慢, 如何處理
分庫分表. 由于歷史訂單使用率并不高, 高頻的可能只是近期訂單, 因此, 將訂單表按照時間進行拆分, 根
據資料量的大小考慮按月分表或按年分表. 訂單ID最好包含時間(如根據雪花演算法生成), 此時既能根據訂
單ID直接獲取到訂單記錄, 也能按照時間進行查詢
為了不影響觀看,本文只截取部分面試內容以及答案,需要的可以【點擊這里,暗號博客園】獲取~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/261607.html
標籤:Java
下一篇:jwt身份驗證
