1. 程式人生 > 其它 >【京東面試覆盤】一面二面真題面經解析

【京東面試覆盤】一面二面真題面經解析

前言

愛因斯坦說過“耐心和恆心總會得到報酬的”,我也一直把這句話當做自己的座右銘,這句箴言在今年也徹底在“我”身上實現了。

京東一面:

為了大家可以直觀的看到,以下是京東一面的相關面試題,下面是解析!

1、遇到過哪些設計模式?

在學習⼀些框架或中介軟體的底層原始碼的時候遇到過⼀些設計模式:

1. 代理模式:Mybatis中⽤到JDK動態代理來⽣成Mapper的代理物件,在執⾏代理物件的⽅法時會去執⾏SQL,Spring中AOP、包括@Configuration註解的底層實現也都⽤到了代理模式

2. 責任鏈模式:Tomcat中的Pipeline實現,以及Dubbo中的Filter機制都使⽤了責任鏈模式

3. ⼯⼚模式:Spring中的BeanFactory就是⼀種⼯⼚模式的實現

4. 介面卡模式:Spring中的Bean銷燬的⽣命週期中⽤到了介面卡模式,⽤來適配各種Bean銷燬邏輯的執⾏⽅式

5. 外觀模式:Tomcat中的Request和RequestFacade之間體現的就是外觀模式

6. 模板⽅法模式:Spring中的refresh⽅法中就提供了給⼦類繼承重寫的⽅法,就⽤到了模板⽅法模式

2、Java死鎖如何避免?

造成死鎖的⼏個原因:

  1. ⼀個資源每次只能被⼀個執行緒使⽤
  2. ⼀個執行緒在阻塞等待某個資源時,不釋放已佔有資源
  3. ⼀個執行緒已經獲得的資源,在未使⽤完之前,不能被強⾏剝奪
  4. 若⼲執行緒形成頭尾相接的迴圈等待資源關係

這是造成死鎖必須要達到的4個條件,如果要避免死鎖,只需要不滿⾜其中某⼀個條件即可。⽽其中前3個條件是作為鎖要符合的條件,所以要避免死鎖就需要打破第4個條件,不出現迴圈等待鎖的關係。

在開發過程中:

  1. 要注意加鎖順序,保證每個執行緒按同樣的順序進⾏加鎖
  2. 要注意加鎖時限,可以針對所設定⼀個超時時間
  3. 要注意死鎖檢查,這是⼀種預防機制,確保在第⼀時間發現死鎖並進⾏解決

3、深拷⻉和淺拷⻉

深拷⻉和淺拷⻉就是指物件的拷⻉,⼀個物件中存在兩種型別的屬性,⼀種是基本資料型別,⼀種是例項物件的引⽤。

  1. 淺拷⻉是指,只會拷⻉基本資料型別的值,以及例項物件的引⽤地址,並不會複製⼀份引⽤地址所指向的物件,也就是淺拷⻉出來的物件,內部的類屬性指向的是同⼀個物件
  2. 深拷⻉是指,既會拷⻉基本資料型別的值,也會針對例項物件的引⽤地址所指向的物件進⾏複製,深拷⻉出來的物件,內部的屬性指向的不是同⼀個物件

4、如果你提交任務時,執行緒池佇列已滿,這時會發⽣什麼

  1. 如果使⽤的⽆界佇列,那麼可以繼續提交任務時沒關係的
  2. 如果使⽤的有界佇列,提交任務時,如果佇列滿了,如果核⼼執行緒數沒有達到上限,那麼則增加執行緒,如果執行緒數已經達到了最⼤值,則使⽤拒絕策略進⾏拒絕

5、談談ConcurrentHashMap的擴容機制

1.7版本

1. 1.7版本的ConcurrentHashMap是基於Segment分段實現的

  1. 每個Segment相對於⼀個⼩型的HashMap
  2. 每個Segment內部會進⾏擴容,和HashMap的擴容邏輯類似
  3. 先⽣成新的陣列,然後轉移元素到新陣列中
  4. 擴容的判斷也是每個Segment內部單獨判斷的,判斷是否超過閾值

1.8版本

1. 1.8版本的ConcurrentHashMap不再基於Segment實現

  1. 當某個執行緒進⾏put時,如果發現ConcurrentHashMap正在進⾏擴容那麼該執行緒⼀起進⾏擴容
  2. 如果某個執行緒put時,發現沒有正在進⾏擴容,則將key-value新增到ConcurrentHashMap中,然後判斷是否超過閾值,超過了則進⾏擴容
  3. ConcurrentHashMap是⽀持多個執行緒同時擴容的
  4. 擴容之前也先⽣成⼀個新的陣列
  5. 在轉移元素時,先將原陣列分組,將每組分給不同的執行緒來進⾏元素的轉移,每個執行緒負責⼀組或多組的元素轉移⼯作

6、Spring中Bean是執行緒安全的嗎?

Spring本身並沒有針對Bean做執行緒安全的處理,所以:

  1. 如果Bean是⽆狀態的,那麼Bean則是執行緒安全的
  2. 如果Bean是有狀態的,那麼Bean則不是執行緒安全的

另外,Bean是不是執行緒安全,跟Bean的作⽤域沒有關係,Bean的作⽤域只是表示Bean的⽣命週期範圍,對於任何⽣命週期的Bean都是⼀個物件,這個物件是不是執行緒安全的,還是得看這個Bean物件本身。

7、說說你常⽤的Linux基本操作命令

  1. 增刪查改
  2. 防⽕牆相關
  3. ssh/scp
  4. 軟體下載、解壓、安裝
  5. 修改許可權

8、Maven中Package和Install的區別

  1. Package是打包,打成Jar或War
  2. Install表示將Jar或War安裝到本地倉庫中

9、項⽬及主要負責的模組

平時要多瞭解⼀下你⽬前在做的項⽬中的核⼼模組,核⼼功能的業務與使⽤到的技術

10、SpringCloud各元件功能,與Dubbo的區別

  1. Eureka:註冊中⼼,⽤來進⾏服務的⾃動註冊和發現
  2. Ribbon:負載均衡元件,⽤來在消費者調⽤服務時進⾏負載均衡
  3. Feign:基於接⼝的申明式的服務調⽤客戶端,讓調⽤變得更簡單
  4. Hystrix:斷路器,負責服務容錯
  5. Zuul:服務⽹關,可以進⾏服務路由、服務降級、負載均衡等
  6. Nacos:分散式配置中⼼以及註冊中⼼
  7. Sentinel:服務的熔斷降級,包括限流
  8. Seata:分散式事務
  9. Spring Cloud Config:分散式配置中⼼
  10. Spring Cloud Bus:訊息匯流排

京東面試真題解析|配套筆記:

Spring Cloud是⼀個微服務框架,提供了微服務領域中的很多功能元件,Dubbo⼀開始是⼀個RPC調⽤框架,核⼼是解決服務調⽤間的問題,Spring Cloud是⼀個⼤⽽全的框架,Dubbo則更側重於服務調⽤,所以Dubbo所提供的功能沒有Spring Cloud全⾯,但是Dubbo的服務調⽤效能⽐Spring Cloud⾼,不過Spring Cloud和Dubbo並不是對⽴的,是可以結合起來⼀起使⽤的。

京東二面:

1、說說類載入器雙親委派模型

JVM中存在三個預設的類載入器:

  1. BootstrapClassLoader
  2. ExtClassLoader
  3. AppClassLoader

AppClassLoader的⽗載入器是ExtClassLoader,ExtClassLoader的⽗載入器是BootstrapClassLoader。

JVM在載入⼀個類時,會調⽤AppClassLoader的loadClass⽅法來載入這個類,不過在這個⽅法中,會先使⽤ExtClassLoader的loadClass⽅法來載入類,同樣ExtClassLoader的loadClass⽅法中會先使⽤BootstrapClassLoader來載入類,如果BootstrapClassLoader載入到了就直接成功,如果BootstrapClassLoader沒有載入到,那麼ExtClassLoader就會⾃⼰嘗試載入該類,如果沒有載入到,那麼則會由AppClassLoader來載入這個類。

所以,雙親委派指得是,JVM在載入類時,會委派給Ext和Bootstrap進⾏載入,如果沒載入到才由⾃⼰進⾏載入。

2、泛型中extends和super的區別

  1. 表示包括T在內的任何T的⼦類
  2. 表示包括T在內的任何T的⽗類

3、併發程式設計三要素?

  1. 原⼦性:不可分割的操作,多個步驟要保證同時成功或同時失敗
  2. 有序性:程式執⾏的順序和程式碼的順序保持⼀致
  3. 可⽤性:⼀個執行緒對共享變數的修改,另⼀個執行緒能⽴⻢看到

4、Spring⽤到了哪些設計模式

5、簡述CAP理論

CAP理論是分散式領域⾮常重要的⼀個理論,很多分散式中介軟體在實現時都需要遵守這個理論,其中:

  1. C表示⼀致性:指的的是分散式系統中的資料的⼀致性
  2. A表示可⽤性:表示分散式系統是否正常可⽤
  3. P表示分割槽容器性:表示分散式系統出現⽹絡問題時的容錯性

CAP理論是指,在分散式系統中不能同時保證C和A,也就是說在分散式系統中要麼保證CP,要麼保證AP,也就是⼀致性和可⽤性只能取其⼀,如果想要資料的⼀致性,那麼就需要損失系統的可⽤性,如果需要系統⾼可⽤,那麼就要損失系統的資料⼀致性,特指強⼀致性。

CAP理論太過嚴格,在實際⽣產環境中更多的是使⽤BASE理論,BASE理論是指分散式系統不需要保證資料的強⼀致,只要做到最終⼀致,也不需要保證⼀直可⽤,保證基本可⽤即可。

6、圖的深度遍歷和⼴度遍歷

  1. 圖的深度優先遍歷是指,從⼀個節點出發,⼀直沿著邊向下深⼊去找節點,如果找不到了則返回上⼀層找其他節點
  2. 圖的⼴度優先遍歷只是,從⼀個節點出發,向下先把第⼀層的節點遍歷完,再去遍歷第⼆層的節點,直到遍歷到最後⼀層

7、快排演算法

快速排序演算法底層採⽤了分治法。

基本思想是:

  1. 先取出數列中的第⼀個數作為基準數
  2. 將數列中⽐基準數⼤的數全部放在它的右邊,⽐基準數⼩的數全部放在它的左邊
  3. 然後在對左右兩部分重複第⼆步,直到各區間只有⼀個數

Java版演算法實現

public class QuickSort {
	public static void quickSort(int[] arr,int low,int high){
		int i,j,temp,t;
		if(low>high){
			return;
		}
		i=low;
		j=high;
		//temp就是基準位 10 temp = arr[low]; 1112 while (i<j) { 13 //先看右邊,依次往左遞減 14 while (temp<=arr[j]&&i<j) {
		j--;
}
//再看左邊,依次往右遞增 
while (temp>=arr[i]&&i<j) {
i++;
}
//如果滿⾜條件則交換 
if (i<j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//最後將基準為與i和j相等位置的數字交換 
arr[low] = arr[i];
arr[i] = temp;
//遞迴調⽤左半陣列 
quickSort(arr, low, j-1);
//遞迴調⽤右半陣列 
quickSort(arr, j+1, high);
}
public static void main(String[] args){
int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
quickSort(arr, 0, arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}

8、TCP的三次握⼿和四次揮⼿

TCP協議是7層⽹絡協議中的傳輸層協議,負責資料的可靠傳輸。

在建⽴TCP連線時,需要通過三次握⼿來建⽴,過程是:

  1. 客戶端向服務端傳送⼀個SYN
  2. 服務端接收到SYN後,給客戶端傳送⼀個SYN_ACK
  3. 客戶端接收到SYN_ACK後,再給服務端傳送⼀個ACK

在斷開TCP連線時,需要通過四次揮⼿來斷開,過程是:

  1. 客戶端向服務端傳送FIN
  2. 服務端接收FIN後,向客戶端傳送ACK,表示我接收到了斷開連線的請求,客戶端你可以不發資料了, 不過服務端這邊可能還有資料正在處理
  3. 服務端處理完所有資料後,向客戶端傳送FIN,表示服務端現在可以斷開連線
  4. 客戶端收到服務端的FIN,向服務端傳送ACK,表示客戶端也會斷開連線了

9、訊息佇列如何保證訊息可靠傳輸

訊息可靠傳輸代表了兩層意思,既不能多也不能少。

  1. 為了保證訊息不多,也就是訊息不能重複,也就是⽣產者不能重複⽣產訊息,或者消費者不能重複消費訊息

a. ⾸先要確保訊息不多發,這個不常出現,也⽐較難控制,因為如果出現了多發,很⼤的原因是⽣產者⾃⼰的原因,如果要避免出現問題,就需要在消費端做控制
b. 要避免不重複消費,最保險的機制就是消費者實現冪等性,保證就算重複消費,也不會有問題,通過冪等性,也能解決⽣產者重複傳送訊息的問題

  1. 訊息不能少,意思就是訊息不能丟失,⽣產者傳送的訊息,消費者⼀定要能消費到,對於這個問題,就要考慮兩個⽅⾯

a. ⽣產者傳送訊息時,要確認broker確實收到並持久化了這條訊息,⽐如RabbitMQ的confirm機制,Kafka的ack機制都可以保證⽣產者能正確的將訊息傳送給broker
b. broker要等待消費者真正確認消費到了訊息時才刪除掉訊息,這⾥通常就是消費端ack機制,消費者接收到⼀條訊息後,如果確認沒問題了,就可以給broker傳送⼀個ack,broker接收到ack後才會刪除訊息

10、畫出項⽬架構圖,介紹⾃⼰所處的模組

需要⼤家⼯作中積極的去了解項⽬架構