2019年最新阿里Java工程師面試題

1、單選題(共10題,每題5分)

關於設計模式遵循的原則,說法錯誤的是?
 
B

設計模式(面向對象)有七大原則,分別是: 1.開放-封閉原則 2.單一職責原則 3.依賴倒轉原則 4.迪米特法則(也稱爲最小知識原則) 5.接口隔離原則 6.合成/聚合複用原則 7.里氏代換原則 詳情參考 :http://www.javashuo.com/article/p-dgyfepja-dx.htmlhtml

 
Mysql索引使用的B-Tree描述錯誤的是?
 
D

B-Tree是知足條件: d>=2,即B-Tree的度; h爲B-Tree的高; 每一個非葉子結點由n-1個key和n個指針組成,其中djava

 
3下列關於Java併發的說法中正確的是()
 
B
B
對於D選項,volatite只保證線程在「加載數據階段」加載的數據是最新的,並不能保證線程安全。
 
**一個線程執行的過程有三個階段:**
加載(複製)主存數據到操做棧 --> 對操做棧數據進行修改 --> 將操做棧數據寫回主存
volatite關鍵字,讓編譯器不去優化代碼使用緩存等,以保證線程在「加載數據階段」加載的數據都是最新的
 
**好比:**
某一時刻i=6是最新的值,volatile保證線程A,B都同時加載了這個最新的值,
而後A執行i(A)+1=7,而後將7寫回主存,
B也執行i(B)+1=7,而後也將7寫回內存,
這樣,執行兩次加法,i卻只增長了1
 
4如下爲求0到1000之內全部奇數和的算法,從中選出描述正確的算法( )
 
A

A和B選項的區別在於第3步和第4步,B中當i=999時,先執行步驟3,則i=i+2=1001,接着第4步s=s+1001,如此看來這種三、4步的寫法求得的S會多加了一個i=1001.mysql

 
5下面關於垃圾收集的說法正確的是
 
D
 
 
6Java虛擬機在運行Java代碼時,首先進行的操做是()
 
C

1)編譯器負責把java文件編譯爲class文件, 2)JAVA虛擬機(JVM)對class文件,進行加載、校驗、執行, 故本題的答案爲C。redis

 

7如下哪一個不是Collection的子接口?
 
D

補圖:算法

 
OpenStack中Mongodb推薦使用( )盤部署。
 
B

sql

 
9如下代碼的循環次數是 ?
 1 public class Test {  
 2  public static void main(String args\[\]) {  
 3  int i = 7;  
 4  do {  
 5  System.out.println(--i);  
 6  --i;  
 7  } while (i != 0);  
 8  System.out.println(i);  
 9  }  
10 }

 

D

數據庫

 
10關於Redis 分佈式鎖的特色描述錯誤的是?
 
B

選項B 應該是 釋放鎖就是刪除 key。編程

RedLock 算法

這個場景是假設有一個 redis cluster,有 5 個 redis master 實例。而後執行以下步驟獲取一把鎖:設計模式

獲取當前時間戳,單位是毫秒; 跟上面相似,輪流嘗試在每一個 master 節點上建立鎖,過時時間較短,通常就幾十毫秒; 嘗試在大多數節點上創建一個鎖,好比 5 個節點就要求是 3 個節點 n / 2 + 1; 客戶端計算創建好鎖的時間,若是創建鎖的時間小於超時時間,就算創建成功了; 要是鎖創建失敗了,那麼就依次以前創建過的鎖刪除; 只要別人創建了一把分佈式鎖,你就得不斷輪詢去嘗試獲取鎖。緩存

 

2、多選題(共10題,每題5分)

1關於MySQL的髒讀、幻讀和不可重複讀說法正確的有?
 
C

髒讀 : 髒讀就是指當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時,另一個事務也訪問這個數據,而後使用了這個數據。 不可重複讀 : 是指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務再修改數據。那麼第一個事務兩次讀到的的數據多是不同的,所以稱爲是不可重複讀。 幻讀: 當某事物正在執行插入或刪除操做同時,第二個事物也在操做此表的數據,就會顯示有一行還未存在的數據,就像發生了幻覺同樣。

解決辦法:若是在操做事務完成數據處理以前,任何其餘事務都不能夠操做此數據,則可避免該問題。

 
JVM管理的內存包括哪幾個運行時數據內存?
 
A,B,C,D

Java虛擬機管理的內存包括幾個運行時數據內存:方法區、虛擬機棧、本地方法棧、堆、程序計數器,其中方法區和堆是由線程共享的數據區,其餘幾個是線程隔離的數據區

 
Redis 內存淘汰機制有哪些?
 
A,B,C

redis 內存淘汰機制有如下幾個:

noeviction: 當內存不足以容納新寫入數據時,新寫入操做會報錯,這個通常沒人用吧,實在是太噁心了。 allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最經常使用的)。 allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個 key,這個通常沒人用吧,爲啥要隨機,確定是把最近最少使用的 key 給幹掉啊。 volatile-lru:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,移除最近最少使用的 key(這個通常不太合適)。 volatile-random:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,隨機移除某個 key。 volatile-ttl:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,有更早過時時間的 key 優先移除。

 
4Hystrix 的設計原則描述正確的有哪些?
 
A,B,C,D

Hystrix 的設計原則

  • 對依賴服務調用時出現的調用延遲和調用失敗進行控制和容錯保護。
  • 在複雜的分佈式系統中,阻止某一個依賴服務的故障在整個系統中蔓延。好比某一個服務故障了,致使其它服務也跟着故障。
  • 提供 fail-fast(快速失敗)和快速恢復的支持。
  • 提供 fallback 優雅降級的支持。
  • 支持近實時的監控、報警以及運維操做。

 

關於Kafka、ActiveMQ、RabbitMQ、RocketMQ說法正確的有?
 
B,C,D

ActiveMQ 基於 Java 開發的, RabbitMQ 是基於 erlang 開發的。 因此選項A 錯誤。 B、C、D都正確。

特性 ActiveMQ RabbitMQ RocketMQ Kafka
單機吞吐量 萬級,比 RocketMQ、Kafka 低一個數量級 同 ActiveMQ 10 萬級,支撐高吞吐 10 萬級,高吞吐,通常配合大數據類的系統來進行實時數據計算、日誌採集等場景
topic 數量對吞吐量的影響     topic 能夠達到幾百/幾千的級別,吞吐量會有較小幅度的降低,這是 RocketMQ 的一大優點,在同等機器下,能夠支撐大量的 topic topic 從幾十到幾百個時候,吞吐量會大幅度降低,在同等機器下,Kafka 儘可能保證 topic 數量不要過多,若是要支撐大規模的 topic,須要增長更多的機器資源
時效性 ms 級 微秒級,這是 RabbitMQ 的一大特色,延遲最低 ms 級 延遲在 ms 級之內
可用性 高,基於主從架構實現高可用 同 ActiveMQ 很是高,分佈式架構 很是高,分佈式,一個數據多個副本,少數機器宕機,不會丟失數據,不會致使不可用
消息可靠性 有較低的機率丟失數據 基本不丟 通過參數優化配置,能夠作到 0 丟失 同 RocketMQ
功能支持 MQ 領域的功能極其完備 基於 erlang 開發,併發能力很強,性能極好,延時很低 MQ 功能較爲完善,仍是分佈式的,擴展性好 功能較爲簡單,主要支持簡單的 MQ 功能,在大數據領域的實時計算以及日誌採集被大規模使用
 
分佈式服務接口的冪等性如何設計(好比不能重複扣款)?
 
A,B,C

分佈式服務接口,只靠數據庫的事務是保證不了冪等性的。 選項D錯誤。

所謂冪等性,就是說一個接口,屢次發起同一個請求,你這個接口得保證結果是準確的,好比不能多扣款、不能多插入一條數據、不能將統計值多加了 1。這就是冪等性。

其實保證冪等性主要是三點:

  • 對於每一個請求必須有一個惟一的標識,舉個栗子:訂單支付請求,確定得包含訂單 id,一個訂單 id 最多支付一次,對吧。
  • 每次處理完請求以後,必須有一個記錄標識這個請求處理過了。常見的方案是在 mysql 中記錄個狀態啥的,好比支付以前記錄一條這個訂單的支付流水。
  • 每次接收請求須要進行判斷,判斷以前是否處理過。好比說,若是有一個訂單已經支付了,就已經有了一條支付流水,那麼若是重複發送這個請求,則此時先插入支付流水,orderId 已經存在了,惟一鍵約束生效,報錯插入不進去的。而後你就不用再扣款了。
  • 實際運做過程當中,你要結合本身的業務來,好比說利用 redis,用 orderId 做爲惟一鍵。只有成功插入這個支付流水,才能夠執行實際的支付扣款。

要求是支付一個訂單,必須插入一條支付流水,order_id 建一個惟一鍵 unique key。你在支付一個訂單以前,先插入一條支付流水,order_id 就已經進去了。你就能夠寫一個標識到 redis 裏面去,set order_id payed,下一次重複請求過來了,先查 redis 的 order_id 對應的 value,若是是 payed 就說明已經支付過了,你就別重複支付了。

 
有哪些方案能夠實現分佈式事務?
 
A,B,C,D

分佈式事務的實現主要有如下 5 種方案:

XA 方案 TCC 方案 本地消息表 可靠消息最終一致性方案 最大努力通知方案 詳情參考 分佈式事務

 
關於緩存雪崩的事前事中過後的解決方案正確的有?
 
A,B,C,D

緩存雪崩的事前事中過後的解決方案以下。

  • 事前:進行系統壓力測試,在負載均衡層作限流處理,過載丟棄請求或者進入隊列
  • 事前:redis 高可用,主從+哨兵,redis cluster,避免全盤崩潰。
  • 事中:本地 ehcache 緩存 + hystrix 限流&降級,避免 MySQL 被打死。
  • 過後:redis 持久化,一旦重啓,自動從磁盤上加載數據,快速恢復緩存數據。
 
如何保證緩存與數據庫的雙寫一致性?
 
A,B,C,D

Cache Aside Pattern 最經典的緩存+數據庫讀寫的模式,就是 Cache Aside Pattern。

讀的時候,先讀緩存,緩存沒有的話,就讀數據庫,而後取出數據後放入緩存,同時返回響應。 更新的時候,先更新數據庫,而後再刪除緩存。 爲何是刪除緩存,而不是更新緩存?

緣由很簡單,不少時候,在複雜點的緩存場景,緩存不僅僅是數據庫中直接取出來的值。

好比可能更新了某個表的一個字段,而後其對應的緩存,是須要查詢另外兩個表的數據並進行運算,才能計算出緩存最新的值的。

另外更新緩存的代價有時候是很高的。是否是說,每次修改數據庫的時候,都必定要將其對應的緩存更新一份?也許有的場景是這樣,可是對於比較複雜的緩存數據計算的場景,就不是這樣了。若是你頻繁修改一個緩存涉及的多個表,緩存也頻繁更新。可是問題在於,這個緩存到底會不會被頻繁訪問到?

舉個栗子,一個緩存涉及的表的字段,在 1 分鐘內就修改了 20 次,或者是 100 次,那麼緩存更新 20 次、100 次;可是這個緩存在 1 分鐘內只被讀取了 1 次,有大量的冷數據。實際上,若是你只是刪除緩存的話,那麼在 1 分鐘內,這個緩存不過就從新計算一次而已,開銷大幅度下降。用到緩存纔去算緩存。

其實刪除緩存,而不是更新緩存,就是一個 lazy 計算的思想,不要每次都從新作複雜的計算,無論它會不會用到,而是讓它到須要被使用的時候再從新計算。像 mybatis,hibernate,都有懶加載思想。查詢一個部門,部門帶了一個員工的 list,沒有必要說每次查詢部門,都裏面的 1000 個員工的數據也同時查出來啊。80% 的狀況,查這個部門,就只是要訪問這個部門的信息就能夠了。先查部門,同時要訪問裏面的員工,那麼這個時候只有在你要訪問裏面的員工的時候,纔會去數據庫裏面查詢 1000 個員工。

 

10 如下對NIO的的描述,正確的有?
 
A,B,C,D

全對,IO和NIO的主要對好比下:

IO NIO
面向流 面向緩衝
阻塞IO 非阻塞IO
選擇器
相關文章
相關標籤/搜索