1. 程式人生 > 其它 >java面試題整理

java面試題整理

springcloud alibaba 的元件 及其作用
nacos:Nacos實現了服務的配置中心與服務註冊發現的功能,Nacos可以通過視覺化的配置降低相關的學習與維護成本,實現動態的配置管理與分環境的配置中心控制
Feign:通過Feign, 我們能把HTTP遠端呼叫對開發者完全透明,得到與呼叫本地方法一致的編碼體驗。
Ribbon:提供客戶端的負載均衡演算法,並提供了完善的配置項如連線超時,重試
gateway:閘道器是整個微服務API請求的入口,負責攔截所有請求,分發到服務上去。可以實現日誌攔截、許可權控制、解決跨域問題、限流、熔斷、負載均衡,隱藏服務端的ip,黑名單與白名單攔截、授權等
Sentinel:Sentinel在網路依賴服務出現高延遲或者失敗時,為系統提供保護和控制;可以進行快速失敗,縮短延遲等待時間;提供失敗回退(Fallback)和相對優雅的服務降級機制;提供有效的服務容錯監控、報警和運維控制手段。
mq的作用是什麼,專案中 mq 的 應用場景
一般用來解決應用解耦,非同步處理,流量削峰等問題,實現高效能,高可用,可伸縮和最終一致性架構。
使用場景:
1.非同步處理
場景說明:使用者註冊後,需要發註冊郵件和註冊簡訊,傳統的做法有兩種 1. 序列的方式 2. 並行的方式
序列方式: 將註冊資訊寫入資料庫後,傳送註冊郵件,再發送註冊簡訊,以上三個任務全部完成後才返回給客戶端。 這有一個問題是,郵件,簡訊並不是必須的,它只是一個通知,而這種做法讓客戶端等待沒有必要等待的東西.
2.應用解耦
場景:雙11是購物狂節,使用者下單後,訂單系統需要通知庫存系統,傳統的做法就是訂單系統呼叫庫存系統的介面.
訂單系統:使用者下單後,訂單系統完成持久化處理,將訊息寫入訊息佇列,返回使用者訂單下單成功。
庫存系統:訂閱下單的訊息,獲取下單訊息,進行庫操作。
就算庫存系統出現故障,訊息佇列也能保證訊息的可靠投遞,不會導致訊息丟失。
3.限流削鋒
場景:秒殺活動,一般會因為流量過大,導致應用掛掉,為了解決這個問題,一般在應用前端加入訊息佇列。
作用:可以控制活動人數,超過此一定閥值的訂單直接丟棄,可以緩解短時間的高流量壓垮應用,使用者的請求,伺服器收到之後,首先寫入訊息佇列,加入訊息佇列長度超過最大值,則直接拋棄使用者請求或跳轉到錯誤頁面.
redis的持久化方式,資料型別有哪些
RDB方式:
RDB(Redis DataBase),是redis預設的儲存方式,RDB方式是通過快照( snapshotting )完成的。它儲存的是某一時刻的資料並不關注過程。RDB儲存redis某一時刻的資料的快照
優點
1.RDB是二進位制壓縮檔案,佔用空間小,便於傳輸(傳給slaver);
2.主程序fork子程序,可以最大化Redis效能;
3.使用RDB檔案來恢復資料較快。
缺點
1、不保證資料完整性,會丟失最後一次快照以後更改的所有資料;
2、父程序在fork子程序的時候如果主程序比較大會阻塞;
AOF方式:
以日誌的形式記錄伺服器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文字的方式記錄,可以
開啟檔案看到詳細的操作記錄
優點:
1、資料安全,Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也
是非同步完成的,其效率也是非常高的,所差的是一旦系統出現宕機現象,那麼這一秒鐘之內修改的資料
將會丟失。而每修改同步,我們可以將其視為同步持久化,即每次發生的資料變化都會被立即記錄到磁
盤中。。
2、通過 append 模式寫檔案,即使中途伺服器宕機也不會破壞已經存在的內容。
3、AOF 機制的 rewrite 模式。定期對AOF檔案進行重寫,以達到壓縮的目的
缺點:
1、AOF 檔案比 RDB 檔案大,且恢復速度慢。
2、資料集大的時候,比 rdb 啟動效率低。
3、執行效率沒有RDB高

AOF檔案比RDB更新頻率高,優先使用AOF還原資料。
AOF比RDB更安全也更大
RDB效能比AOF好
如果兩個都配了優先載入AOF
常用的集合及其特性
List集合:
1、ArrayList(最常用)
底層是動態陣列,故優缺點同陣列:查詢快,增刪慢
執行緒不安全,效率高
2、LinkedList
底層是連結串列,(巧記:和陣列優缺點互補)查詢慢,增刪快
執行緒不安全,效率高
Set集合:
1、LinkedHashSet
底層是:雜湊表(元素不可重複)+連結串列(有序,因為連結串列記錄每個元素都記錄後一個元素的地址)
1、去掉重複元素
2、具備先進先出的特點
1、HashSet
底層是雜湊表
向HashSet集合中放入新元素的執行順序:
1、呼叫Hashcode()函式,看是否已經有相同的雜湊值,如果沒有則放入該新元素,如果有則呼叫equals()函式逐個比對,如果沒有,則放入,如果有,則不執行新增元素操作。
3、TreeSet
底層是紅黑樹,自然平衡二叉樹,因為是二叉樹結構所以集合內元素自動按升序排列(升序是其最大特徵)。
元素不可重複
Map集合:
1、HashMap
底層是雜湊表(雜湊表的本質是陣列+連結串列)
把它的鍵套用HashSet的規則即可,只是每個鍵都附帶了其各自的值。
2、LinkedHashMap
底層是雜湊表和連結串列
把它的鍵套用LinkedHashSet的規則即可,只是每個鍵都附帶了其各自的值。
3、Hashtable
底層是雜湊表(雜湊表的本質是陣列+連結串列),十分類似於HashMap
與HashMap唯一區別:Hashtable執行緒安全,效率低,不允許null鍵null值
HashMap執行緒不安全,效率高,允許null鍵null值
4、TreeMap
底層是紅黑樹,自然平衡二叉樹
其鍵的儲存類似於TreeSet,只是每個鍵都附帶了其各自的值(value)。
springbean 的生命週期
1、解析類得到BeanDefinition
2、如果有多個構造方法,則要推斷構造方法
3、確定好構造方法後,進行例項化得到一個物件
4、對物件中的加了@Autowired註解的屬性進行屬性填充
5、回撥Aware方法,比如BeanNameAware,BeanFactoryAware
6、呼叫BeanPostProcessor的初始化前的方法
7、呼叫初始化方法
8、呼叫BeanPostProcessor的初始化後的方法,在這裡會進行AOP
9、如果當前建立的bean是單例的則會把bean放入單例池
10、使用bean
11、Spring容器關閉時呼叫DisposableBean中destory()方法
aop的底層原理
Spring AOP使用動態代理技術在執行期織入增強的程式碼,他使用了兩種代理機制:一種是基於JDK的動態代理;另一種是基於CGLib的動態代理。
JDK動態代理
JDK動態代理主要涉及兩個類:Proxy和InvocationHandler。InvocationHandler是一個介面,可以通過實現該介面定義橫切邏輯,並通過反射機制呼叫目標類的程式碼,動態地將橫切邏輯和業務邏輯編織在一起。
CGLib動態代理
CGLib採用底層的位元組碼技術,可以為一個類建立子類,在子類中採用方法攔截的技術攔截所有父類方法的呼叫並順勢織入橫切邏輯。需要注意的是,由於CGLib採用動態建立子類的方式生成代理物件,所以不能對目標類中的final或private方法進行代理。
elk 是什麼
ELK是一套針對日誌資料做解決方案的框架,分別代表了三款產品: - E: ElasticSearch(ES),負責日誌的儲存和檢索; - L:Logstash,負責日誌的收集,過濾和格式化; - K:Kibana,負責日誌的展示統計和資料視覺化;
arraylist和 hashmap 底層特徵
arraylist
底層實現:是基於陣列實現的,是一個動態陣列,其容量能自動增長。
ArrayList進行新增元素的操作的時候是分兩個步驟進行的,即第一步先在object[size]的位置上存放需要新增的元素;第二步將size的值增加1。由於這個過程在多執行緒的環境下是不能保證具有原子性的,因此ArrayList在多執行緒的環境下是執行緒不安全的。他的擴容機制就是:當第一次插入元素時才分配10(預設)個物件空間。假如有20個數據需要新增,那麼會分別在第一次的時候,將ArrayList的容量變為10 (如下圖一);之後擴容會按照1.5倍增長。也就是當新增第11個數據的時候,Arraylist繼續擴容變為101.5=15(如下圖二);當新增第16個數據時,繼續擴容變為15 * 1.5 =22個
hashmap
底層實現:陣列+連結串列+紅黑樹
jdk8開始連結串列高度到8、陣列長度超過64,連結串列轉變為紅黑樹,元素以內部類Node節點存在
計算key的hash值,二次hash然後對陣列長度取模,對應到陣列下標,
如果沒有產生hash衝突(下標位置沒有元素),則直接建立Node存入陣列,
如果產生hash衝突,先進行equal比較,相同則取代該元素,不同,則判斷連結串列高度插入連結串列,鏈
表高度達到8,並且陣列長度到64則轉變為紅黑樹,長度低於6則將紅黑樹轉回連結串列
key為null,存在下標0的位置
記憶體洩漏與記憶體溢位????
記憶體洩露 memory leak :是指程式在申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩露危害可以忽略,但記憶體洩露堆積後果很嚴重,無論多少記憶體 ,遲早會被佔光 會最終會導致 記憶體溢位。
記憶體溢位 out of memory :是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現 out of memory
引起記憶體溢位的原因:
1、記憶體中載入的資料量過於龐大,如一次從資料庫取出過多資料;
2、 集合類中有對物件的引用,使用完後未清空,使得 JVM 不能回收;
3、程式碼中存在死迴圈或迴圈產生過多重複的物件實體;
4、啟動引數記憶體值設定的過小
記憶體溢位的解決方案:
第一步,修改 JVM 啟動引數,直接增加記憶體。 (-Xms , -Xmx 引數一定不要忘記加。 )
第二步,檢查錯誤日誌,檢視 “ OutOfMemory ”錯誤前是否有其它異常或錯誤。
第三步,對程式碼進行走查和分析,找出可能發生記憶體溢位的位置。
重點排查以下幾點:
1、檢查對資料庫查詢中,是否有一次獲得全部資料的查詢
2、檢查程式碼中是否有死迴圈或遞迴呼叫。
3、檢查是否有大迴圈重複產生新物件實體。
4、 檢查 List 、 MAP 等集合物件是否有使用完後,未清除的問題
延時訊息的實現方式
佇列ttl+死信exchange
使用兩個佇列,一個佇列接收訊息不消費,等待指定時間後訊息死亡,再由該佇列繫結的死信exchange再次將其路由到另一個佇列提供業務消費。
我這裡也簡單介紹下:
rabbitmq 可以給 訊息 和 佇列 設定 ttl(生存時間)
● 佇列設定:x-message-ttl=60000 (佇列中所有訊息都只有60s存活時間)
● 指定訊息設定:expire=60000 指定訊息只有60s存活時間
● 先宣告一個消費佇列 queue_dlx,用來接收死信訊息,並提供消費;
然後宣告一個死信exchange_dlx, 繫結 queue_dlx,接收訊息後路由至queue_dlx;
宣告一個延遲佇列,queue_delay, 用來接收業務訊息,但不提供消費,等待訊息死亡後轉至死信exchange。(即延遲)
宣告一個exchange,由業務傳送訊息到exchange,然後轉至queue_delay.
將不同延時等級的訊息放入不同queue中,然後轉發到目標topic
先宣告一個topic型別的死信exchange,用來轉發死信(延時後)的訊息。
定義一組用來暫存訊息的延時delayQueue,並設定死信exchange,死信路由預設為訊息原始路由。
再宣告一個topic型別的延時exchange與延時queue繫結,繫結路由為$delayQueueName.#, 即通過routing key字首識別應轉發到哪個延時佇列。
然後宣告需要消費的業務佇列 bizQueue,再將其繫結到死信exchange上,路由關係為

.$bizQueueName (也可以是正常的routingKey, 這個死信exchange的繫結關係就和普通定義傳送訊息的定義差不多了)
最後傳送訊息時,根據其延時等級,在routingKey前面拼接上對應的 delayQueueName 就可以了。

什麼情況下訊息會進死信佇列
● 訊息被拒絕(basic.reject / basic.nack),並且requeue = false
● 訊息TTL過期
● 佇列達到最大長度