令人痛哭的10道題答案解析

1.正確答案【A】

答案解析

Dubbo提供了隨機、輪詢、最少調用優先等多種負載均衡策略,提供對zk等多種註冊中心等支持,能夠自動完成服務的註冊與發現。dubbo提供可視化的管理後臺,方便對服務狀態進行監控和管理。dubbo的數據通信默認使用netty來實現,擁有非常不錯的性能。Dubbo默認的容錯方案是Failover Cluster,即:失敗自動切換,當出現失敗,重試其它服務器。

除此之外,還提供以下其他容錯方式:

Failfast Cluster

快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。

Failsafe Cluster

失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。

Failback Cluster

失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作。

Forking Cluster

並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=”2″ 來設置最大並行數。

Broadcast Cluster

廣播調用所有提供者,逐個調用,任意一臺報錯則報錯 。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

2.正確答案【B、D】

答案解析

令人痛哭的10道題答案解析

令人痛哭的10道題答案解析

Kafka只保證一個分區內的消息有序,不能保證一個topic的不同分區之間的消息有序。

為了保證較高的處理效率,所有的消息讀寫都是在主patition中進行,其他副本分區只會從主分區複製數據。Kafka會在Zookeeper上針對每個Topic維護一個稱為ISR(in-sync replica),就是已同步的副本集。如果某個主分區不可用了,Kafka就會從ISR集合中選擇一個副本作為新的主分區。

消息的發送有三種方式:同步、異步以及oneway。同步模式下後臺線程中發送消息時同步獲取結果,這也是默認模式。

異步的模式允許生產者批量發送數據,可以極大的提高性能,但是會增加丟失數據的風險。oneway模式只發送消息不需要返回發送結果,消息可靠性最低,但是低延遲、高吞吐,適用於對可靠性要求不高的場景

3.正確答案【A、B、D】

答案解析

快速排序時間複雜度:

  1. 最優情況:被選出來的基準值都是當前子數組的中間數。
    不斷地把一個規模為 n 的問題分解成規模為 n/2 的問題,一直分解到規模大小為 1。如果 n 等於 2,只需要分一次;如果 n 等於 4,需要分 2 次,以此類推,對於規模為 n 的問題,一共要進行 log(n) 次的切分。

    把規模大小為 n 的問題分解成 n/2 的兩個子問題時,和基準值進行了 n-1 次比較,複雜度就是 O(n)。
    因此,在最優情況下,快速排序的複雜度是 O(nlogn)。
  2. 最壞情況:基準值選擇了子數組裡的最大或者最小值
    每次都把子數組分成了兩個更小的子數組,其中一個的長度為 1,另外一個的長度只比原子數組少 1,這樣就需要n次的切分。
    因此,算法複雜度為 O(n的平方)。

4.正確答案【A、B、C、D】

答案解析

虛擬機棧 也叫方法棧,是線程私有的,線程在執行每個方法時都會同時創建一個棧幀,用來存儲局部變量表、操作棧、動態鏈接、方法出口等信息。調用方法時執行入棧,方法返回時執行出棧。

本地方法棧與虛擬機棧類似,也是用來保存線程執行方法時的信息,不同的是,執行java方法使用虛擬機棧,而執行native方法使用本地方法棧。

程序計數器 保存著當前線程所執行的字節碼位置,每個線程工作時都有一個獨立的計數器。程序計數器為執行java方法服務,執行native方法時,程序計數器為空。

棧、本地方法棧、程序計數器這三個部分都是線程獨佔的。

堆 是JVM管理的內存中最大的一塊,堆被所有線程共享,目的是為了存放對象實例,幾乎所有的對象實例都在這裡分配。當堆內存沒有可用的空間時,會拋出OOM異常。根據對象存活的週期不同,jvm把堆內存進行分代管理,由垃圾回收器來進行對象的回收管理。

方法區 也是各個線程共享的內存區域,又叫非堆區。用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據,JDK7中的永久代和JDK8中的Metaspace都是方法區的一種實現。

5.正確答案【A、D】

答案解析

令人痛哭的10道題答案解析

A.等待2倍最大報文段生存時間之後在關閉鏈接,原因有兩個:一、保證TCP協議的全雙工連接能夠可靠關閉二、保證這次連接的重複數據段從網絡中消失,防止端口被重用時可能產生數據混淆

B.shutdown可以使TCP半雙工,但是如果之前調用了close,則直接關閉了socket

C.收到了ack之後的狀態,也是不能發只能收,進入FINWAIT2通信中client和server兩端的鏈接都是ESTABLISHED狀態,然後client先主動發起了關閉鏈接請求,client向server發送了一個fin包,表示client端已經沒有數據要發送了,然後client進入了FINWAIT1狀態。

server端收到fin後,返回ack,然後進入CLOSE_WAIT狀態。此時server屬於半關閉狀態,因為此時client向server方向已經不會發送數據了,可是server向client端可能還有數據要發送。

當server端數據發送完畢後,server端會向client端發送fin,表示server端也沒有數據要發送了,此時server進入LAST_ACK狀態,就等待client的應答就可以關閉鏈接了。

client端收到server端的fin後,回覆ack,然後進入TIMEWAIT狀態。TIMEWAIT狀態下需要等待2倍的最大報文段生存時間,來保證鏈接的可靠關閉。之後才會進入CLOSED關閉狀態。而server端收到ack後直接就進入CLOSED狀態。

D.由於TCP的下層網絡(IP)可能出現丟失、重複或失序的情況,TCP協議提供可靠數據傳輸服務。為保證數據傳輸的正確性,TCP會重傳其認為已丟失(包括報文中的比特錯誤)的包。

6.正確答案【A、B、C】

答案解析

b+樹更適合索引系統,原因有:

  1. 由於葉節點之間有指針相連,b+樹更適合範圍檢索;
  2. 由於非頁節點只保存關鍵字和指針,同樣大小非葉節點,b+樹可以容納更多的關鍵字,可以降低樹高,查詢時磁盤讀寫代價更低;
  3. B+樹的查詢效率比較穩定。任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,效率相當。

7.正確答案【A、B、C、D】

答案解析

netty線程模型採用“服務端監聽線程”和“IO線程”分離的方式,boss線程組負責監聽事件,創建socket並綁定到worker線程組。

worker線程組負責io處理。線程組由eventLoopGroup實現,其中包含了多個EventLoop事件處理器,每個EventLoop包含一個處理線程。

通常情況下在NIO非阻塞模式下,Netty為每個Channel分配一個EventLoop,並且它的整個生命週期中的事件都由這個EventLoop來處理。

一個eventLoop可以綁定多個Channel。

eventLoop的處理模型,netty4中channel的讀寫事件都是由worker線程來處理。請求處理中最主要的就是channelPipeline,其中包含了一組channelHandler。這些handler組成了責任鏈模式,依次對channel中的消息進行處理。

一般接收消息時,由pipeline處理完成會把消息提交到業務線程池進行處理,當業務線程處理完成時,會封裝成task,提交回channel對應的eventLoop來寫回返回值。


8.正確答案【B】

答案解析

令人痛哭的10道題答案解析

在執行sql時,首先會從SqlSessionFactory中創建一個新的SqlSession。sql語句是通過sqlSession中的Executor來執行,Executor根據SqlSession傳遞的參數執行query()方法,然後創建一個StatementHandler對象,將必要的參數傳遞給StatementHandler,由StatementHandler來完成對數據庫的查詢。

StatementHandler調用ParameterHandler的setParameters方法,把用戶傳遞的參數轉換成JDBC Statement所需要的參數, 調用原生JDBC來執行語句。

最後由ResultSetHandler的handleResultSets方法對JDBC返回的ResultSet結果集轉換成對象集,並逐級返回結果,完成一次sql語句執行。

9.正確答案【B】

答案解析

令人痛哭的10道題答案解析

我們看看向線程池提交任務時的執行順序。

向線程池提交任務時,會首先判斷線程池中的線程數是否大於設置的核心線程數,如果不大於,就創建一個核心線程來執行任務。

如果大於核心線程數,就會判斷緩衝隊列是否滿了,如果沒有滿,則放入隊列,等待線程空閒時執行任務。

如果隊列已經滿了,則判斷是否達到了線程池設置的最大線程數,如果沒有達到,就創建新線程來執行任務。

如果已經達到了最大線程數,則執行指定的拒絕策略。

10.正確答案【A】

答案解析

令人痛哭的10道題答案解析

類的加載指的是將編譯好的class類文件中的字節碼讀入到內存中,將其放在方法區內並創建對應的Class對象。

類的加載分為加載、鏈接、初始化,其中鏈接又包括驗證、準備、解析三步。看到圖中上半部分深綠色,我們逐個分析:

加載是文件到內存的過程。通過類的完全限定名查找此類字節碼文件,並利用字節碼文件創建一個Class對象

驗證是對類文件內容驗證。目的在於確保Class文件符合當前虛擬機要求,不會危害虛擬機自身安全。主要包括四種:文件格式驗證,元數據驗證,字節碼驗證,符號引用驗證。

準備階段是進行內存分配。為類變量也就是類中由static修飾的變量分配內存,並且設置初始值,這裡要注意,初始值是0或者null,而不是代碼中設置的具體值,代碼中設置的值是在初始化階段完成的。另外這裡也不包含用final修飾的靜態變量,因為final在編譯的時候就會分配了。

解析主要是解析字段、接口、方法。主要是將常量池中的符號引用替換為直接引用的過程。直接引用就是直接指向目標的指針、相對偏移量等。

最後是初始化:主要完成靜態塊執行與靜態變量的賦值。這是類加載最後階段,若被加載類的父類沒有初始化,則先對父類進行初始化。

只有對類主動使用時,才會進行初始化,初始化的觸發條件包括創建類的實例的時候、訪問類的靜態方法或者靜態變量的時候、Class.forName()反射類的時候、或者某個子類被初始化的時候


分享到:


相關文章: