
今日小編給大家分享一個福利,就是關于面試的一些建議,還有就是分享面試題,以及解析。
今天主要分享Java的面試,後續會分享後端(c++/Golang/PHP/Python)視覺算法,推薦算法,導航算法,視訊算法,大資料開發,資料挖掘等面試題。
面試題,主要來源于我們的一些内推的朋友以及在網上總的一些總結。希望對大家有所幫助。

先說說面試,面試一般會分為四面,第一面一般是同級别(或者比你高一點級别)的面試,二面是leader面,三面是部門負責人面試,最後是HR面試。
一面的面試官一般會根據你的履歷涉及到的項目來問,讓你描述項目你所擔任的角色,你所做的事情,會問的比較的細,在這個過程中,你需要有邏輯的把整個項目用比較合适的點貫穿,還有,你要把自己做的事情,描述的很詳細,讓面試官感覺這個項目你擔任的位置是比較重要的,而不是打雜,如果你真的是打雜,那你要多多做做功課了。注意:劃重點,如果不是自己做的,自己對這個也不是很熟悉,請不要硬套在自己身上,記住,面試官不是傻子,看的出來的。
二面,一般是你的直屬leader面試,他面試也會了解你的之前的經曆,但是這個不是最主要的,最主要的是他會和你聊來這邊會接手什麼項目,這個項目用到的技術棧,然後看你對技術棧的掌握程度,這個時候,請一定仔細看崗位的JD,在面試過程中,對這個技術詳細的了解。
三面,部門負責人,他的面試相對于之前會比較輕松,原因在于,你的技術起碼來說已經勉勉強強的過關了,那麼他會涉及到你的定級,他所考察的就是你的能力,一般會給一些場景,問你如何實作,這個時候,就是把之前的技術合理的運用的時候了。
備注:有些兩輪面試或者進階别面試的第一輪一般是直屬leader面試,進階别還有交叉面試等,這個私聊小編,小編再細細和你們探讨。

下面我們來說說JAVA的面試,面試官都喜歡問那些問題:
- spring架構,最近,Springboot/Springcloud是履歷一涉及就必考的問題(劃重點)
- netty和epoll的原理,netty的類
- Java開發多線程相關的問題
- JVM調優(進階一定考,關于jvm調優,本公衆号有幾篇文章詳細的介紹了jvm調優的幾個方面,大家有空可以多看看)
- 容器,設計模式,Hibernate,Redis(進階和中級的差別就在這兒了),RabbitMQ,MySQL等等。
-
福利——Java的88道面試題,助你順利拿下offer~

1. JDK 和 JRE 有什麼差別?
· JDK:Java Development Kit 的簡稱,Java 開發工具包,提供了 Java 的開發環境和運作環境。
· JRE:Java Runtime Environment 的簡稱,Java 運作環境,為 Java 的運作提供了所需環境。
具體來說 JDK 其實包含了 JRE,同時還包含了編譯 Java 源碼的編譯器 Javac,還包含了很多 Java 程式調試和分析的工具。簡單來說:如果你需要運作 Java 程式,隻需安裝 JRE 就可以了,如果你需要編寫 Java 程式,需要安裝 JDK。
2. Java 中的 Math. round(-1. 5) 等于多少?
等于 -1,因為在數軸上取值時,中間值(0.5)向右取整,是以正 0.5 是往上取整,負 0.5 是直接舍棄。
3.String 屬于基礎的資料類型嗎?
String 不屬于基礎類型,基礎類型有 8 種:byte、boolean、char、short、int、float、long、double,而 String 屬于對象。
4.Java 中操作字元串都有哪些類?它們之間有什麼差別?
操作字元串的類有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的差別在于 String 聲明的是不可變的對象,每次操作都會生成新的 String 對象,然後将指針指向新的 String 對象,而 StringBuffer、StringBuilder 可以在原有對象的基礎上進行操作,是以在經常改變字元串内容的情況下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的差別在于,StringBuffer 是線程安全的,而 StringBuilder 是非線程安全的,但 StringBuilder 的性能卻高于 StringBuffer,是以在單線程環境下推薦使用 StringBuilder,多線程環境下推薦使用 StringBuffer。
5.如何将字元串反轉?(經常考)
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
示例代碼:
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba
6.String 類的常用方法都有那些?
· indexOf():傳回指定字元的索引。
· charAt():傳回指定索引處的字元。
· replace():字元串替換。
· trim():去除字元串兩端空白。
· split():分割字元串,傳回一個分割後的字元串數組。
· getBytes():傳回字元串的 byte 類型數組。
· length():傳回字元串長度。
· toLowerCase():将字元串轉成小寫字母。
· toUpperCase():将字元串轉成大寫字元。
· substring():截取字元串。
· equals():字元串比較。
7.Java 中 IO 流分為幾種?
按功能來分:輸入流(input)、輸出流(output)。
按類型來分:位元組流和字元流。
位元組流和字元流的差別是:位元組流按 8 位傳輸以位元組為機關輸入輸出資料,字元流按 16 位傳輸以字元為機關輸入輸出資料
8.BIO、NIO、AIO 有什麼差別?
· BIO:Block IO 同步阻塞式 IO,就是我們平常使用的傳統 IO,它的特點是模式簡單使用友善,并發處理能力低。
· NIO:Non IO 同步非阻塞 IO,是傳統 IO 的更新,用戶端和伺服器端通過 Channel(通道)通訊,實作了多路複用。
· AIO:Asynchronous IO 是 NIO 的更新,也叫 NIO2,實作了異步非堵塞 IO ,異步 IO 的操作基于事件和回調機制。
9.HashMap 和 Hashtable 有什麼差別?
· 存儲:HashMap 運作 key 和 value 為 null,而 Hashtable 不允許。
· 線程安全:Hashtable 是線程安全的,而 HashMap 是非線程安全的。
· 推薦使用:在 Hashtable 的類注釋可以看到,Hashtable 是保留類不建議使用,推薦在單線程環境下使用 HashMap 替代,如果需要多線程使用則用 ConcurrentHashMap 替代。
10.如何決定使用 HashMap 還是 TreeMap?
對于在 Map 中插入、删除、定位一個元素這類操作,HashMap 是最好的選擇,因為相對而言 HashMap 的插入會更快,但如果你要對一個 key 集合進行有序的周遊,那 TreeMap 是更好的選擇。
11.說一下 HashMap 的實作原理?(經常考)
HashMap 基于 Hash 算法實作的,我們通過 put(key,value)存儲,get(key)來擷取。當傳入 key 時,HashMap 會根據 key. hashCode() 計算出 hash 值,根據 hash 值将 value 儲存在 bucket 裡。當計算出的 hash 值相同時,我們稱之為 hash 沖突,HashMap 的做法是用連結清單和紅黑樹存儲相同 hash 值的 value。當 hash 沖突的個數比較少時,使用連結清單否則使用紅黑樹。
12.并行和并發有什麼差別?
· 并行:多個處理器或多核處理器同時處理多個任務。
· 并發:多個任務在同一個 CPU 核上,按細分的時間片輪流(交替)執行,從邏輯上來看那些任務是同時執行。
如下圖:
并發 = 兩個隊列和一台咖啡機。
并行 = 兩個隊列和兩台咖啡機。
13.線程和程序的差別?(送分題)
一個程式下至少有一個程序,一個程序下至少有一個線程,一個程序下也可以有多個線程來增加程式的執行速度。
14.sleep() 和 wait() 有什麼差別?
· 類的不同:sleep() 來自 Thread,wait() 來自 Object。
· 釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
· 用法不同:sleep() 時間到會自動恢複;wait() 可以使用 notify()/notifyAll()直接喚醒。
15.建立線程池有哪幾種方式?
線程池建立有七種方式,最核心的是最後一種:
· newSingleThreadExecutor():它的特點在于工作線程數目被限制為 1,操作一個無界的工作隊列,是以它保證了所有任務的都是被順序執行,最多會有一個任務處于活動狀态,并且不允許使用者改動線程池執行個體,是以可以避免其改變線程數目;
· newCachedThreadPool():它是一種用來處理大量短時間工作任務的線程池,具有幾個鮮明特點:它會試圖緩存線程并重用,當無緩存線程可用時,就會建立新的工作線程;如果線程閑置的時間超過 60 秒,則被終止并移出緩存;長時間閑置時,這種線程池,不會消耗什麼資源。其内部使用 SynchronousQueue 作為工作隊列;
· newFixedThreadPool(int nThreads):重用指定數目(nThreads)的線程,其背後使用的是無界的工作隊列,任何時候最多有 nThreads 個工作線程是活動的。這意味着,如果任務數量超過了活動隊列數目,将在工作隊列中等待空閑線程出現;如果有工作線程退出,将會有新的工作線程被建立,以補足指定的數目 nThreads;
· newSingleThreadScheduledExecutor():建立單線程池,傳回 ScheduledExecutorService,可以進行定時或周期性的工作排程;
· newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()類似,建立的是個 ScheduledExecutorService,可以進行定時或周期性的工作排程,差別在于單一工作線程還是多個工作線程;
· newWorkStealingPool(int parallelism):這是一個經常被人忽略的線程池,Java 8 才加入這個建立方法,其内部會建構ForkJoinPool,利用Work-Stealing算法,并行地處理任務,不保證處理順序;
· ThreadPoolExecutor():是最原始的線程池建立,上面1-3建立方式都是對ThreadPoolExecutor的封裝。
16.
在 Java 程式中怎麼保證多線程的運作安全?
· 方法一:使用安全類,比如 Java. util. concurrent 下的類。
· 方法二:使用自動鎖 synchronized。
· 方法三:使用手動鎖 Lock。
手動鎖 Java 示例代碼如下:
Lock lock = new ReentrantLock();
lock. lock();
try {
System. out. println("獲得鎖");
} catch (Exception e) {
// TODO: handle exception
} finally {
System. out. println("釋放鎖");
lock. unlock();
}
17.多線程中 synchronized 鎖更新的原理是什麼?
synchronized 鎖更新原理:在鎖對象的對象頭裡面有一個 threadid 字段,在第一次通路的時候 threadid 為空,jvm 讓其持有偏向鎖,并将 threadid 設定為其線程 id,再次進入的時候會先判斷 threadid 是否與其線程 id 一緻,如果一緻則可以直接使用此對象,如果不一緻,則更新偏向鎖為輕量級鎖,通過自旋循環一定次數來擷取鎖,執行一定次數之後,如果還沒有正常擷取到要使用的對象,此時就會把鎖從輕量級更新為重量級鎖,此過程就構成了 synchronized 鎖的更新。
鎖的更新的目的:鎖更新是為了減低了鎖帶來的性能消耗。在 Java 6 之後優化 synchronized 的實作方式,使用了偏向鎖更新為輕量級鎖再更新到重量級鎖的方式,進而減低了鎖帶來的性能消耗。
18.什麼是死鎖?怎麼防止死鎖?
當線程 A 持有獨占鎖a,并嘗試去擷取獨占鎖 b 的同時,線程 B 持有獨占鎖 b,并嘗試擷取獨占鎖 a 的情況下,就會發生 AB 兩個線程由于互相持有對方需要的鎖,而發生的阻塞現象,我們稱為死鎖。
· 盡量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設定逾時時間,逾時可以退出防止死鎖。
· 盡量使用 Java. util. concurrent 并發類代替自己手寫鎖。
· 盡量降低鎖的使用粒度,盡量不要幾個功能用同一把鎖。
· 盡量減少同步的代碼塊。
19.說一下 synchronized 底層實作原理?
synchronized 是由一對 monitorenter/monitorexit 指令實作的,monitor 對象是同步的基本實作單元。在 Java 6 之前,monitor 的實作完全是依靠作業系統内部的互斥鎖,因為需要進行使用者态到核心态的切換,是以同步操作是一個無差别的重量級操作,性能也很低。但在 Java 6 的時候,Java 虛拟機 對此進行了大刀闊斧地改進,提供了三種不同的 monitor 實作,也就是常說的三種不同的鎖:偏向鎖(Biased Locking)、輕量級鎖和重量級鎖,大大改進了其性能。
20.synchronized 和 ReentrantLock 差別是什麼?
synchronized 早期的實作比較低效,對比 ReentrantLock,大多數場景性能都相差較大,但是在 Java 6 中對 synchronized 進行了非常多的改進。
主要差別如下:
· ReentrantLock 使用起來比較靈活,但是必須有釋放鎖的配合動作;
· ReentrantLock 必須手動擷取與釋放鎖,而 synchronized 不需要手動釋放和開啟鎖;
· ReentrantLock 隻适用于代碼塊鎖,而 synchronized 可用于修飾方法、代碼塊等。
· volatile 标記的變量不會被編譯器優化;synchronized 标記的變量可以被編譯器優化。
21.什麼是 Java 序列化?什麼情況下需要序列化?
Java 序列化是為了儲存各種對象在記憶體中的狀态,并且可以把儲存的對象狀态再讀出來。
以下情況需要使用 Java 序列化:
· 想把的記憶體中的對象狀态儲存到一個檔案中或者資料庫中時候;
· 想用套接字在網絡上傳送對象的時候;
· 想通過RMI(遠端方法調用)傳輸對象的時候。
22. 為什麼要使用克隆?
克隆的對象可能包含一些已經修改過的屬性,而 new 出來的對象的屬性都還是初始化時候的值,是以當需要一個新的對象來儲存目前對象的“狀态”就靠克隆方法了。
23. 如何實作對象克隆?
· 實作 Cloneable 接口并重寫 Object 類中的 clone() 方法。
· 實作 Serializable 接口,通過對象的序列化和反序列化實作克隆,可以實作真正的深度克隆。
24. 深拷貝和淺拷貝差別是什麼?
· 淺克隆:當對象被複制時隻複制它本身和其中包含的值類型的成員變量,而引用類型的成員對象并沒有複制。
· 深克隆:除了對象本身被複制外,對象所包含的所有成員變量也将複制。
25.JSP 有哪些内置對象?作用分别是什麼?
JSP 有 9 大内置對象:
· request:封裝用戶端的請求,其中包含來自 get 或 post 請求的參數;
· response:封裝伺服器對用戶端的響應;
· pageContext:通過該對象可以擷取其他對象;
· session:封裝使用者會話的對象;
· application:封裝伺服器運作環境的對象;
· out:輸出伺服器響應的輸出流對象;
· config:Web 應用的配置對象;
· page:JSP 頁面本身(相當于 Java 程式中的 this);
exception:封裝頁面抛出異常的對象。
26.JSP 的 4 種作用域?
· page:代表與一個頁面相關的對象和屬性。
· request:代表與用戶端發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個 Web 元件;需要在頁面顯示的臨時資料可以置于此作用域。
· session:代表與某個使用者與伺服器建立的一次會話相關的對象和屬性。跟某個使用者相關的資料應該放在使用者自己的 session 中。
· application:代表與整個 Web 應用程式相關的對象和屬性,它實質上是跨越整個 Web 應用程式,包括多個頁面、請求和會話的一個全局作用域。
27說一下 session 的工作原理?
session 的工作原理是用戶端登入完成之後,伺服器會建立對應的 session,session 建立完之後,會把 session 的 id 發送給用戶端,用戶端再存儲到浏覽器中。這樣用戶端每次通路伺服器時,都會帶着 sessionid,伺服器拿到 sessionid 之後,在記憶體找到與之對應的 session 這樣就可以正常工作了。
28. spring mvc 和 struts 的差別是什麼?
· 攔截級别:struts2 是類級别的攔截;spring mvc 是方法級别的攔截。
· 資料獨立性:spring mvc 的方法之間基本上獨立的,獨享 request 和 response 資料,請求資料通過參數擷取,處理結果通過 ModelMap 交回給架構,方法之間不共享變量;而 struts2 雖然方法之間也是獨立的,但其所有 action 變量是共享的,這不會影響程式運作,卻給我們編碼和讀程式時帶來了一定的麻煩。
· 攔截機制:struts2 有以自己的 interceptor 機制,spring mvc 用的是獨立的 aop 方式,這樣導緻struts2 的配置檔案量比 spring mvc 大。
· 對 ajax 的支援:spring mvc 內建了ajax,所有 ajax 使用很友善,隻需要一個注解 @ResponseBody 就可以實作了;而 struts2 一般需要安裝插件或者自己寫代碼才行。
29.final、finally、finalize 有什麼差別?
· final:是修飾符,如果修飾類,此類不能被繼承;如果修飾方法和變量,則表示此方法和此變量不能在被改變,隻能使用。
· finally:是 try{} catch{} finally{} 最後一部分,表示不論發生任何情況都會執行,finally 部分可以省略,但如果 finally 部分存在,則一定會執行 finally 裡面的代碼。
30.常見的異常類有哪些?
· NullPointerException 空指針異常
· ClassNotFoundException 指定類不存在
· NumberFormatException 字元串轉換為數字異常
· IndexOutOfBoundsException 數組下标越界異常
· ClassCastException 資料類型轉換異常
· FileNotFoundException 檔案未找到異常
· NoSuchMethodException 方法不存在異常
· IOException IO 異常
· SocketException Socket 異常
31.簡述 tcp 和 udp的差別?
tcp 和 udp 是 OSI 模型中的運輸層中的協定。tcp 提供可靠的通信傳輸,而 udp 則常被用于讓廣播和細節控制交給應用的通信傳輸。
兩者的差別大緻如下:
· tcp 面向連接配接,udp 面向非連接配接即發送資料前不需要建立連結;
· tcp 提供可靠的服務(資料傳輸),udp 無法保證;
· tcp 面向位元組流,udp 面向封包;
· tcp 資料傳輸慢,udp 資料傳輸快;
32.tcp 為什麼要三次握手,兩次不行嗎?為什麼?(劃重點)
如果采用兩次握手,那麼隻要伺服器發出确認資料包就會建立連接配接,但由于用戶端此時并未響應伺服器端的請求,那此時伺服器端就會一直在等待用戶端,這樣伺服器端就白白浪費了一定的資源。若采用三次握手,伺服器端沒有收到來自用戶端的再此确認,則就會知道用戶端并沒有要求建立請求,就不會浪費伺服器的資源。
33.說一下你熟悉的設計模式?(劃重點)
· 單例模式:保證被建立一次,節省系統開銷。
· 工廠模式(簡單工廠、抽象工廠):解耦代碼。
· 觀察者模式:定義了對象之間的一對多的依賴,這樣一來,當一個對象改變時,它的所有的依賴者都會收到通知并自動更新。
· 外觀模式:提供一個統一的接口,用來通路子系統中的一群接口,外觀定義了一個高層的接口,讓子系統更容易使用。
· 模版方法模式:定義了一個算法的骨架,而将一些步驟延遲到子類中,模版方法使得子類可以在不改變算法結構的情況下,重新定義算法的步驟。
· 狀态模式:允許對象在内部狀态改變時改變它的行為,對象看起來好像修改了它的類。
34.簡單工廠和抽象工廠有什麼差別?
· 簡單工廠:用來生産同一等級結構中的任意産品,對于增加新的産品,無能為力。
· 工廠方法:用來生産同一等級結構中的固定産品,支援增加任意産品。
· 抽象工廠:用來生産不同産品族的全部産品,對于增加新的産品,無能為力;支援增加産品族。
35.為什麼要使用 spring?
· spring 提供 ioc 技術,容器會幫你管理依賴的對象,進而不需要自己建立和管理依賴對象了,更輕松的實作了程式的解耦。
· spring 提供了事務支援,使得事務操作變的更加友善。
· spring 提供了面向切片程式設計,這樣可以更友善的處理某一類的問題。
· 更友善的架構內建,spring 可以很友善的內建其他架構,比如 MyBatis、hibernate 等。
36.spring 有哪些主要子產品?
· spring core:架構的最基礎部分,提供 ioc 和依賴注入特性。
· spring context:建構于 core 封裝包基礎上的 context 封裝包,提供了一種架構式的對象通路方法。
· spring dao:Data Access Object 提供了JDBC的抽象層。
· spring aop:提供了面向切面的程式設計實作,讓你可以自定義攔截器、切點等。
· spring Web:提供了針對 Web 開發的內建特性,例如檔案上傳,利用 servlet listeners 進行 ioc 容器初始化和針對 Web 的 ApplicationContext。
· spring Web mvc:spring 中的 mvc 封裝包提供了 Web 應用的 Model-View-Controller(MVC)的實作。
37.spring 支援幾種 bean 的作用域?
spring 支援 5 種作用域,如下:
· singleton:spring ioc 容器中隻存在一個 bean 執行個體,bean 以單例模式存在,是系統預設值;
· prototype:每次從容器調用 bean 時都會建立一個新的示例,既每次 getBean()相當于執行 new Bean()操作;
· Web 環境下的作用域:
· request:每次 http 請求都會建立一個 bean;
· session:同一個 http session 共享一個 bean 執行個體;
· global-session:用于 portlet 容器,因為每個 portlet 有單獨的 session,globalsession 提供一個全局性的 http session。
注意: 使用 prototype 作用域需要慎重的思考,因為頻繁建立和銷毀 bean 會帶來很大的性能開銷。
38.說一下 spring mvc 運作流程?
· spring mvc 先将請求發送給 DispatcherServlet。
· DispatcherServlet 查詢一個或多個 HandlerMapping,找到處理請求的 Controller。
· DispatcherServlet 再把請求送出到對應的 Controller。
· Controller 進行業務邏輯處理後,會傳回一個ModelAndView。
· Dispathcher 查詢一個或多個 ViewResolver 視圖解析器,找到 ModelAndView 對象指定的視圖對象。
· 視圖對象負責渲染傳回給用戶端。
39,spring mvc 有哪些元件?
· 前置控制器 DispatcherServlet。
· 映射控制器 HandlerMapping。
· 處理器 Controller。
· 模型和視圖 ModelAndView。
· 視圖解析器 ViewResolver。
40.為什麼要用 spring boot?(劃重點)
· 配置簡單
· 獨立運作
· 自動裝配
· 無代碼生成和 xml 配置
· 提供應用監控
· 易上手
· 提升開發效率
spring boot 核心配置檔案是什麼?
spring boot 核心的兩個配置檔案:
· bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加載的,比 applicaton 優先加載,且 boostrap 裡面的屬性不能被覆寫;
· application (. yml 或者 . properties):用于 spring boot 項目的自動化配置。
spring boot 配置檔案有哪幾種類型?它們有什麼差別?
配置檔案有 . properties 格式和 . yml 格式,它們主要的差別是書法風格不同。
. properties 配置如下:
spring. RabbitMQ. port=5672
. yml 配置如下:
spring:
RabbitMQ:
port: 5672
. yml 格式不支援 @PropertySource 注解導入。
spring boot 有哪些方式可以實作熱部署?
· 使用 devtools 啟動熱部署,添加 devtools 庫,在配置檔案中把 spring. devtools. restart. enabled 設定為 true;
使用 Intellij Idea 編輯器,勾上自動編譯或手動重新編譯。
41.jpa 和 hibernate 有什麼差別?
jpa 全稱 Java Persistence API,是 Java 持久化接口規範,hibernate 屬于 jpa 的具體實作。
42. spring cloud 斷路器的作用是什麼?
在分布式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之後,通過斷路器的故障監控(類似熔斷保險絲),向調用方傳回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長時間占用不釋放,避免了故障在分布式系統中的蔓延。
43.spring cloud 的核心元件有哪些?
· Eureka:服務注冊于發現。
· Feign:基于動态代理機制,根據注解和選擇的機器,拼接請求 url 位址,發起請求。
· Ribbon:實作負載均衡,從一個服務的多台機器中選擇一台。
· Hystrix:提供線程池,不同的服務走不同的線程池,實作了不同服務調用的隔離,避免了服務雪崩的問題。
· Zuul:網關管理,由 Zuul 網關轉發請求給對應的服務。
44.為什麼要使用 hibernate?
· hibernate 是對 jdbc 的封裝,大大簡化了資料通路層的繁瑣的重複性代碼。
· hibernate 是一個優秀的 ORM 實作,很多程度上簡化了 DAO 層的編碼功能。
· 可以很友善的進行資料庫的移植工作。
· 提供了緩存機制,是程式執行更改的高效。
hibernate 有幾種查詢方式?
三種:hql、原生 SQL、條件查詢 Criteria。
45.
hibernate 是如何工作的?
· 讀取并解析配置檔案。
· 讀取并解析映射檔案,建立 SessionFactory。
· 打開 Session。
· 建立事務。
· 進行持久化操作。
· 送出事務。
· 關閉 Session。
· 關閉 SessionFactory。
45.說一下 hibernate 的緩存機制?
hibernate 常用的緩存有一級緩存和二級緩存:
一級緩存:也叫 Session 緩存,隻在 Session 作用範圍内有效,不需要使用者幹涉,由 hibernate 自身維護,可以通過:evict(object)清除 object 的緩存;clear()清除一級緩存中的所有緩存;flush()刷出緩存;
二級緩存:應用級别的緩存,在所有 Session 中都有效,支援配置第三方的緩存,如:EhCache。
46.hibernate 實體類必須要有無參構造函數嗎?為什麼?
hibernate 中每個實體類必須提供一個無參構造函數,因為 hibernate 架構要使用 reflection api,通過調用 ClassnewInstance() 來建立實體類的執行個體,如果沒有無參的構造函數就會抛出異常。
47.MyBatis 中 #{}和 ${}的差別是什麼?
\#{}是預編譯處理,${}是字元替換。 在使用 #{}時,MyBatis 會将 SQL 中的 #{}替換成“?”,配合 PreparedStatement 的 set 方法指派,這樣可以有效的防止 SQL 注入,保證程式的運作安全。
48.MyBatis 有幾種分頁方式?
分頁方式:邏輯分頁和實體分頁。
邏輯分頁: 使用 MyBatis 自帶的 RowBounds 進行分頁,它是一次性查詢很多資料,然後在資料中再進行檢索。
實體分頁: 自己手寫 SQL 分頁或使用分頁插件 PageHelper,去資料庫查詢指定條數的分頁資料的形式。
49.MyBatis 是否支援延遲加載?延遲加載的原理是什麼?
MyBatis 支援延遲加載,設定 lazyLoadingEnabled=true 即可。
延遲加載的原理的是調用的時候觸發加載,而不是在初始化的時候就加載資訊。比如調用 a. getB(). getName(),這個時候發現 a. getB() 的值為 null,此時會單獨觸發事先儲存好的關聯 B 對象的 SQL,先查詢出來 B,然後再調用 a. setB(b),而這時候再調用 a. getB(). getName() 就有值了,這就是延遲加載的基本原理。
50.MyBatis 和 hibernate 的差別有哪些?
· 靈活性:MyBatis 更加靈活,自己可以寫 SQL 語句,使用起來比較友善。
· 可移植性:MyBatis 有很多自己寫的 SQL,因為每個資料庫的 SQL 可以不相同,是以可移植性比較差。
· 學習和使用門檻:MyBatis 入門比較簡單,使用門檻也更低。
· 二級緩存:hibernate 擁有更好的二級緩存,它的二級緩存可以自行更換為第三方的二級緩存。
51.MyBatis 分頁插件的實作原理是什麼?
分頁插件的基本原理是使用 MyBatis 提供的插件接口,實作自定義插件,在插件的攔截方法内攔截待執行的 SQL,然後重寫 SQL,根據 dialect 方言,添加對應的實體分頁語句和實體分頁參數。
52.RabbitMQ 的使用場景有哪些?
· 搶購活動,削峰填谷,防止系統崩塌。
· 延遲資訊處理,比如 10 分鐘之後給下單未付款的使用者發送郵件提醒。
· 解耦系統,對于新增的功能可以單獨寫子產品擴充,比如使用者确認評價之後,新增了給使用者返積分的功能,這個時候不用在業務代碼裡添加新增積分的功能,隻需要把新增積分的接口訂閱确認評價的消息隊列即可,後面再添加任何功能隻需要訂閱對應的消息隊列即可。
53.RabbitMQ 叢集中唯一一個磁盤節點崩潰了會發生什麼情況?
如果唯一磁盤的磁盤節點崩潰了,不能進行以下操作:
· 不能建立隊列
· 不能建立交換器
· 不能建立綁定
· 不能添加使用者
· 不能更改權限
· 不能添加和删除叢集節點
唯一磁盤節點崩潰了,叢集是可以保持運作的,但你不能更改任何東西。
54.什麼情況會導緻 kafka 運作變慢?
· cpu 性能瓶頸
· 磁盤讀寫瓶頸
· 網絡瓶頸
55.使用 kafka 叢集需要注意什麼?
· 叢集的數量不是越多越好,最好不要超過 7 個,因為節點越多,消息複制需要的時間就越長,整個群組的吞吐量就越低。
· 叢集數量最好是單數,因為超過一半故障叢集就不能用了,設定為單數容錯率更高。
56.zookeeper 都有哪些功能?
· 叢集管理:監控節點存活狀态、運作請求等。
· 主節點選舉:主節點挂掉了之後可以從備用的節點開始新一輪選主,主節點選舉說的就是這個選舉的過程,使用 zookeeper 可以協助完成這個過程。
· 分布式鎖:zookeeper 提供兩種鎖:獨占鎖、共享鎖。獨占鎖即一次隻能有一個線程使用資源,共享鎖是讀鎖共享,讀寫互斥,即可以有多線線程同時讀同一個資源,如果要使用寫鎖也隻能有一個線程使用。zookeeper可以對分布式鎖進行控制。
· 命名服務:在分布式系統中,通過使用命名服務,用戶端應用能夠根據指定名字來擷取資源或服務的位址,提供者等資訊。
zookeeper 有幾種部署模式?
zookeeper 有三種部署模式:
· 單機部署:一台叢集上運作;
· 叢集部署:多台叢集運作;
· 僞叢集部署:一台叢集啟動多個 zookeeper 執行個體運作。
zookeeper 怎麼保證主從節點的狀态同步?
zookeeper 的核心是原子廣播,這個機制保證了各個 server 之間的同步。實作這個機制的協定叫做 zab 協定。zab 協定有兩種模式,分别是恢複模式(選主)和廣播模式(同步)。當服務啟動或者在上司者崩潰後,zab 就進入了恢複模式,當上司者被選舉出來,且大多數 server 完成了和 leader 的狀态同步以後,恢複模式就結束了。狀态同步保證了 leader 和 server 具有相同的系統狀态。
57.資料庫的三範式是什麼?
· 第一範式:強調的是列的原子性,即資料庫表的每一列都是不可分割的原子資料項。
· 第二範式:要求實體的屬性完全依賴于主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性。
· 第三範式:任何非主屬性不依賴于其它非主屬性。
58.Redis 是什麼?都有哪些使用場景?
Redis 是一個使用 C 語言開發的高速緩存資料庫。
Redis 使用場景:
· 記錄文章點贊數、點選數、評論數;
· 緩存近期熱帖;
· 緩存文章詳情資訊;
· 記錄使用者會話資訊。
59.Redis 有哪些功能?
· 資料緩存功能
· 分布式鎖的功能
· 支援資料持久化
· 支援事務
· 支援消息隊列
60.Redis 和 memcache 有什麼差別?
· 存儲方式不同:memcache 把資料全部存在記憶體之中,斷電後會挂掉,資料不能超過記憶體大小;Redis 有部份存在硬碟上,這樣能保證資料的持久性。
· 資料支援類型:memcache 對資料類型支援相對簡單;Redis 有複雜的資料類型。
· 使用底層模型不同:它們之間底層實作方式,以及與用戶端之間通信的應用協定不一樣,Redis 自己建構了 vm 機制,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求。
· value 值大小不同:Redis 最大可以達到 512mb;memcache 隻有 1mb。
61.Redis 常見的性能問題有哪些?該如何解決?
· 主伺服器寫記憶體快照,會阻塞主線程的工作,當快照比較大時對性能影響是非常大的,會間斷性暫停服務,是以主伺服器最好不要寫記憶體快照。
· Redis 主從複制的性能問題,為了主從複制的速度和連接配接的穩定性,主從庫最好在同一個區域網路内。
62. Redis 淘汰政策有哪些?
· volatile-lru:從已設定過期時間的資料集(server. db[i]. expires)中挑選最近最少使用的資料淘汰。
· volatile-ttl:從已設定過期時間的資料集(server. db[i]. expires)中挑選将要過期的資料淘汰。
· volatile-random:從已設定過期時間的資料集(server. db[i]. expires)中任意選擇資料淘汰。
· allkeys-lru:從資料集(server. db[i]. dict)中挑選最近最少使用的資料淘汰。
· allkeys-random:從資料集(server. db[i]. dict)中任意選擇資料淘汰。
63.Redis 怎麼實作分布式鎖?
Redis 分布式鎖其實就是在系統裡面占一個“坑”,其他程式也要占“坑”的時候,占用成功了就可以繼續執行,失敗了就隻能放棄或稍後重試。
占坑一般使用 setnx(set if not exists)指令,隻允許被一個程式占有,使用完調用 del 釋放鎖。
64.Redis 如何做記憶體優化?
盡量使用 Redis 的散清單,把相關的資訊放到散清單裡面存儲,而不是把每個字段單獨存儲,這樣可以有效的減少記憶體使用。比如将 Web 系統的使用者對象,應該放到散清單裡面再整體存儲到 Redis,而不是把使用者的姓名、年齡、密碼、郵箱等字段分别設定 key 進行存儲。
65.Redis 淘汰政策有哪些?
· no-enviction(驅逐):禁止驅逐資料。
65.Redis 持久化有幾種方式?
Redis 的持久化有兩種方式,或者說有兩種政策:
· RDB(Redis Database):指定的時間間隔能對你的資料進行快照存儲。
· AOF(Append Only File):每一個收到的寫指令都通過write函數追加到檔案中。
66.Redis 支援的資料類型有哪些?
Redis 支援的資料類型:string(字元串)、list(清單)、hash(字典)、set(集合)、zset(有序集合)。
67.什麼是緩存穿透?怎麼解決?
緩存穿透:指查詢一個一定不存在的資料,由于緩存是不命中時需要從資料庫查詢,查不到資料則不寫入緩存,這将導緻這個不存在的資料每次請求都要到資料庫去查詢,造成緩存穿透。
解決方案:最簡單粗暴的方法如果一個查詢傳回的資料為空(不管是資料不存在,還是系統故障),我們就把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
68.說一下樂觀鎖和悲觀鎖?
· 樂觀鎖:每次去拿資料的時候都認為别人不會修改,是以不會上鎖,但是在送出更新的時候會判斷一下在此期間别人有沒有去更新這個資料。
· 悲觀鎖:每次去拿資料的時候都認為别人會修改,是以每次在拿資料的時候都會上鎖,這樣别人想拿這個資料就會阻止,直到這個鎖被釋放。
69.MySQL 問題排查都有哪些手段?
· 使用 show processlist 指令檢視目前所有連接配接資訊。
· 使用 explain 指令查詢 SQL 語句執行計劃。
· 開啟慢查詢日志,檢視慢查詢的 SQL。
70.Java記憶體模型是什麼?
Java記憶體模型規定和指引Java程式在不同的記憶體架構、CPU和作業系統間有确定性地行為。它在多線程的情況下尤其重要。Java記憶體模型對一個線程所做的變動能被其它線程可見提供了保證,它們之間是先行發生關系。這個關系定義了一些規則讓程式員在并發程式設計時思路更清晰。比如,先行發生關系確定了:
線程内的代碼能夠按先後順序執行,這被稱為程式次序規則。
對于同一個鎖,一個解鎖操作一定要發生在時間上後發生的另一個鎖定操作之前,也叫做管程鎖定規則。
前一個對volatile的寫操作在後一個volatile的讀操作之前,也叫volatile變量規則。
一個線程内的任何操作必需在這個線程的start()調用之後,也叫作線程啟動規則。
一個線程的所有操作都會線上程終止之前,線程終止規則。
一個對象的終結操作必需在這個對象構造完成之後,也叫對象終結規則。
可傳遞性
71.Java常用包有那些?
Java.lang
Java.io
Java.sql
Java.util
Java.awt
Java.net
Java.math
71.tringBuffer,Stringbuilder有什麼差別?
StringBuffer與StringBuilder都繼承了AbstractStringBulder類,而AbtractStringBuilder又實作了CharSequence接口,兩個類都是用來進行字元串操作的。
在做字元串拼接修改删除替換時,效率比string更高。
StringBuffer是線程安全的,Stringbuilder是非線程安全的。是以Stringbuilder比stringbuffer效率更高,StringBuffer的方法大多都加了synchronized關鍵字
72.String類的常用方法有那些?
charAt:傳回指定索引處的字元
indexOf():傳回指定字元的索引
replace():字元串替換
trim():去除字元串兩端空白
split():分割字元串,傳回一個分割後的字元串數組
getBytes():傳回字元串的byte類型數組
length():傳回字元串長度
toLowerCase():将字元串轉成小寫字母
toUpperCase():将字元串轉成大寫字元
substring():截取字元串
format():格式化字元串
equals():字元串比較
73.接口有什麼特點?
接口中聲明全是public static final修飾的常量
接口中所有方法都是抽象方法
接口是沒有構造方法的
接口也不能直接執行個體化
接口可以多繼承
74.常用io類有那些?
File
FileInputSteam,FileOutputStream
BufferInputStream,BufferedOutputSream
PrintWrite
FileReader,FileWriter
BufferReader,BufferedWriter
ObjectInputStream,ObjectOutputSream
75.
線程同步的方法
wait():讓線程等待。将線程存儲到一個線程池中。
notify():喚醒被等待的線程。通常都喚醒線程池中的第一個。讓被喚醒的線程處于臨時阻塞狀态。
notifyAll(): 喚醒所有的等待線程。将線程池中的所有線程都喚醒。
76.重載與重寫
Overload為重載,Override為重寫方法的重寫和重載是Java多态性的不同表現。重寫是父類與子類之間多态性的一種表現,重載是一個類中多态性的一種表現。
如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Override)。子類的對象使用這個方法時,将調用子類中的定義,對它而言,父類中的定義如同被"屏蔽"了。
如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overload)。
重載的方法是可以改變傳回值的類型。
77.說一下 JVM 運作時資料區?
不同虛拟機的運作時資料區可能略微有所不同,但都會遵從 Java 虛拟機規範, Java 虛拟機規範規定的區域分為以下 5 個部分:
· 程式計數器(Program Counter Register):目前線程所執行的位元組碼的行号訓示器,位元組碼解析器的工作是通過改變這個計數器的值,來選取下一條需要執行的位元組碼指令,分支、循環、跳轉、異常處理、線程恢複等基礎功能,都需要依賴這個計數器來完成;
· Java 虛拟機棧(Java Virtual Machine Stacks):用于存儲局部變量表、操作數棧、動态連結、方法出口等資訊;
· 本地方法棧(Native Method Stack):與虛拟機棧的作用是一樣的,隻不過虛拟機棧是服務 Java 方法的,而本地方法棧是為虛拟機調用 Native 方法服務的;
· Java 堆(Java Heap):Java 虛拟機中記憶體最大的一塊,是被所有線程共享的,幾乎所有的對象執行個體都在這裡配置設定記憶體;
· 方法區(Methed Area):用于存儲已被虛拟機加載的類資訊、常量、靜态變量、即時編譯後的代碼等資料。
78.說一下 JVM 有哪些垃圾回收器?
· Serial:最早的單線程串行垃圾回收器。
· Serial Old:Serial 垃圾回收器的老年版本,同樣也是單線程的,可以作為 CMS 垃圾回收器的備選預案。
· ParNew:是 Serial 的多線程版本。
· Parallel 和 ParNew 收集器類似是多線程的,但 Parallel 是吞吐量優先的收集器,可以犧牲等待時間換取系統的吞吐量。
· Parallel Old 是 Parallel 老生代版本,Parallel 使用的是複制的記憶體回收算法,Parallel Old 使用的是标記-整理的記憶體回收算法。
· CMS:一種以獲得最短停頓時間為目标的收集器,非常适用 B/S 系統。
· G1:一種兼顧吞吐量和停頓時間的 GC 實作,是 JDK 9 以後的預設 GC 選項。
79.說一下 JVM 調優的工具?
JDK 自帶了很多監控工具,都位于 JDK 的 bin 目錄下,其中最常用的是 jconsole 和 jvisualvm 這兩款視圖監控工具。
· jconsole:用于對 JVM 中的記憶體、線程和類等進行監控;
· jvisualvm:JDK 自帶的全能分析工具,可以分析:記憶體快照、線程快照、程式死鎖、監控記憶體的變化、gc 變化等。
80.常用的 JVM 調優的參數都有哪些?
· -Xms2g:初始化推大小為 2g;
· -Xmx2g:堆最大記憶體為 2g;
· -XX:NewRatio=4:設定年輕的和老年代的記憶體比例為 1:4;
· -XX:SurvivorRatio=8:設定新生代 Eden 和 Survivor 比例為 8:2;
· –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器組合;
· -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器組合;
· -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器組合;
· -XX:+PrintGC:開啟列印 gc 資訊;
· -XX:+PrintGCDetails:列印 gc 詳細資訊。
81.詳細介紹一下 CMS 垃圾回收器?
CMS 是英文 Concurrent Mark-Sweep 的簡稱,是以犧牲吞吐量為代價來獲得最短回收停頓時間的垃圾回收器。對于要求伺服器響應速度的應用上,這種垃圾回收器非常适合。在啟動 JVM 的參數加上“-XX:+UseConcMarkSweepGC”來指定使用 CMS 垃圾回收器。
CMS 使用的是标記-清除的算法實作的,是以在 gc 的時候回産生大量的記憶體碎片,當剩餘記憶體不能滿足程式運作要求時,系統将會出現 Concurrent Mode Failure,臨時 CMS 會采用 Serial Old 回收器進行垃圾清除,此時的性能将會被降低。
82.新生代垃圾回收器和老生代垃圾回收器都有哪些?有什麼差別?
· 新生代回收器:Serial、ParNew、Parallel Scavenge
· 老年代回收器:Serial Old、Parallel Old、CMS
· 整堆回收器:G1
新生代垃圾回收器一般采用的是複制算法,複制算法的優點是效率高,缺點是記憶體使用率低;老年代回收器一般采用的是标記-整理的算法進行垃圾回收。
83.一下 JVM 有哪些垃圾回收算法?
· 标記-清除算法:标記無用對象,然後進行清除回收。缺點:效率不高,無法清除垃圾碎片。
· 标記-整理算法:标記無用對象,讓所有存活的對象都向一端移動,然後直接清除掉端邊界以外的記憶體。
· 複制算法:按照容量劃分二個大小相等的記憶體區域,當一塊用完的時候将活着的對象複制到另一塊上,然後再把已使用的記憶體空間一次清理掉。缺點:記憶體使用率不高,隻有原來的一半。
· 分代算法:根據對象存活周期的不同将記憶體劃分為幾塊,一般是新生代和老年代,新生代基本采用複制算法,老年代采用标記整理算法。
84.說一下 JVM 的主要組成部分?及其作用?
· 類加載器(ClassLoader)
· 運作時資料區(Runtime Data Area)
· 執行引擎(Execution Engine)
· 本地庫接口(Native Interface)
元件的作用: 首先通過類加載器(ClassLoader)會把 Java 代碼轉換成位元組碼,運作時資料區(Runtime Data Area)再把位元組碼加載到記憶體中,而位元組碼檔案隻是 JVM 的一套指令集規範,并不能直接交給底層作業系統去執行,是以需要特定的指令解析器執行引擎(Execution Engine),将位元組碼翻譯成底層系統指令,再交由 CPU 去執行,而這個過程中需要調用其他語言的本地庫接口(Native Interface)來實作整個程式的功能。
85.說一下 JVM 運作時資料區?
86.說一下堆棧的差別?
· 功能方面:堆是用來存放對象的,棧是用來執行程式的。
· 共享性:堆是線程共享的,棧是線程私有的。
· 空間大小:堆大小遠遠大于棧。
87.隊列和棧是什麼?有什麼差別?
隊列和棧都是被用來預存儲資料的。
隊列允許先進先出檢索元素,但也有例外的情況,Deque 接口允許從兩端檢索元素。
棧和隊列很相似,但它運作對元素進行後進先出進行檢索。
88.Java 中都有哪些引用類型?
· 強引用:發生 gc 的時候不會被回收。
· 軟引用:有用但不是必須的對象,在發生記憶體溢出之前會被回收。
· 弱引用:有用但不是必須的對象,在下一次GC時會被回收。
· 虛引用(幽靈引用/幻影引用):無法通過虛引用獲得對象,用 PhantomReference 實作虛引用,虛引用的用途是在 gc 時傳回一個通知。
關于JVM的調優,大家請翻閱前面的文章,寫的非常的詳細。