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


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

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

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

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

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

 
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,如此看來這種3、4步的寫法求得的S會多加了一個i=1001.

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

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

 

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

補圖:

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

 
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; 客戶端計算建立好鎖的時間,如果建立鎖的時間小於超時時間,就算建立成功了; 要是鎖建立失敗了,那么就依次之前建立過的鎖刪除; 只要別人建立了一把分布式鎖,你就得不斷輪詢去嘗試獲取鎖。

 

二、多選題(共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
選擇器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM