主頁 > 後端開發 > 大廠面試系列一些問題的答案

大廠面試系列一些問題的答案

2020-12-24 06:46:04 後端開發

知識點總結

  • InnoDB的行鎖

    (1)共享鎖(S):用法lock in share mode,又稱讀鎖,允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖,若事務T對資料物件A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖,這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改, (2)排他鎖(X):用法for update,又稱寫鎖,允許獲取排他鎖的事務更新資料,阻止其他事務取得相同的資料集共享讀鎖和排他寫鎖,若事務T對資料物件A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖,在沒有索引的情況下,InnoDB只能使用表鎖

  • Spring的事務傳播級別

    (1)REQUIRED(默認):支持使用當前事務,如果當前事務不存在,創建一個新事務, (2)SUPPORTS:支持使用當前事務,如果當前事務不存在,則不使用事務, (3)MANDATORY:強制,支持使用當前事務,如果當前事務不存在,則拋出Exception, (4)REQUIRES_NEW:創建一個新事務,如果當前事務存在,把當前事務掛起, (5)NOT_SUPPORTED:無事務執行,如果當前事務存在,把當前事務掛起, (6)NEVER:無事務執行,如果當前有事務則拋出Exception, (7)NESTED:嵌套事務,如果當前事務存在,那么在嵌套的事務中執行,如果當前事務不存在,則表現跟REQUIRED一樣,

  • Redis與Mysql雙寫一致性方案

先更新資料庫,再刪快取,資料庫的讀操作的速度遠快于寫操作的,所以臟資料很難出現,可以對異步延時洗掉策略,保證讀請求完成以后,再進行洗掉操作

  • 索引B+樹的葉子節點都可以存哪些東西?

可能存盤的是整行資料,也有可能是主鍵的值,B+樹的葉子節點存盤了整行資料的是主鍵索引,也被稱之為聚簇索引,而索引B+ Tree的葉子節點存盤了主鍵的值的是非主鍵索引,也被稱之為非聚簇索引

  • 分代回收

(1)HotSpot JVM把年輕代分為了三部分:1個Eden區和2個Survivor區(分別叫from和to),一般情況下,新創建的物件都會被分配到Eden區(一些大物件特殊處理),這些物件經過第一次Minor GC后,如果仍然存活,將會被移到Survivor區,物件在Survivor區中每熬過一次Minor GC,年齡就會增加1歲,當它的年齡增加到一定程度時,就會被移動到年老代中, (2)因為年輕代中的物件基本都是朝生夕死的,所以在年輕代的垃圾回收演算法使用的是復制演算法,復制演算法的基本思想就是將記憶體分為兩塊,每次只用其中一塊,當這一塊記憶體用完,就將還活著的物件復制到另外一塊上面,復制演算法不會產生記憶體碎片, (3)在GC開始的時候,物件只會存在于Eden區和名為“From”的Survivor區,Survivor區“To”是空的,緊接著進行GC,Eden區中所有存活的物件都會被復制到“To”,而在“From”區中,仍存活的物件會根據他們的年齡值來決定去向,年齡達到一定值(年齡閾值,可以通過-XX:MaxTenuringThreshold來設定)的物件會被移動到年老代中,沒有達到閾值的物件會被復制到“To”區域,經過這次GC后,Eden區和From區已經被清空,這個時候,“From”和“To”會交換他們的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”,不管怎樣,都會保證名為To的Survivor區域是空的,Minor GC會一直重復這樣的程序,直到“To”區被填滿,“To”區被填滿之后,會將所有物件移動到年老代中,

  • 執行緒之間如何通信?

(1)利用最基本的synchronized (2)利用synchronized、notify、wait (3)while輪詢的方式 (4)利用Lock和Condition (5)利用volatile (6)利用AtomicInteger (7)利用CyclicBarrier (8)利用PipedInputStream (9)利用BlockingQueue

  • redis并發競爭key的解決方案

(1)分布式鎖+時間戳 (2)利用訊息佇列

  • 如何避免(預防)死鎖?

破壞“請求和保持”條件:讓行程在申請資源時,一次性申請所有需要用到的資源,不要一次一次來申請,當申請的資源有一些沒空,那就讓執行緒等待,不過這個方法比較浪費資源,行程可能經常處于饑餓狀態,還有一種方法是,要求行程在申請資源前,要釋放自己擁有的資源, 破壞“不可搶占”條件:允許行程進行搶占,方法一:如果去搶資源,被拒絕,就釋放自己的資源,方法二:作業系統允許搶,只要你優先級大,可以搶到, 破壞“回圈等待”條件:將系統中的所有資源統一編號,行程可在任何時刻提出資源申請,但所有申請必須按照資源的編號順序提出(指定獲取鎖的順序,順序加鎖)

  • 高并發系統的設計與實作

在開發高并發系統時有三把利器用來保護系統:快取、降級和限流, (1)快取:快取比較好理解,在大型高并發系統中,如果沒有快取資料庫將分分鐘被爆,系統也會瞬間癱瘓,使用快取不單單能夠提升系統訪問速度、提高并發訪問量,也是保護資料庫、保護系統的有效方式,大型網站一般主要是“讀”,快取的使用很容易被想到,在大型“寫”系統中,快取也常常扮演者非常重要的角色,比如累積一些資料批量寫入,記憶體里面的快取佇列(生產消費),以及HBase寫資料的機制等等也都是通過快取提升系統的吞吐量或者實作系統的保護措施,甚至訊息中間件,你也可以認為是一種分布式的資料快取, (2)降級:服務降級是當服務器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行,降級往往會指定不同的級別,面臨不同的例外等級執行不同的處理,根據服務方式:可以拒接服務,可以延遲服務,也有時候可以隨機服務,根據服務范圍:可以砍掉某個功能,也可以砍掉某些模塊,總之服務降級需要根據不同的業務需求采用不同的降級策略,主要的目的就是服務雖然有損但是總比沒有好, (3)限流:限流可以認為服務降級的一種,限流就是限制系統的輸入和輸出流量已達到保護系統的目的,一般來說系統的吞吐量是可以被測算的,為了保證系統的穩定運行,一旦達到的需要限制的閾值,就需要限制流量并采取一些措施以完成限制流量的目的,比如:延遲處理,拒絕處理,或者部分拒絕處理等等,

  • 高并發系統的限流如何實作?

常見的限流演算法有計數器、漏桶和令牌桶演算法,漏桶演算法在分布式環境中訊息中間件或者Redis都是可選的方案,發放令牌的頻率增加可以提升整體資料處理的速度,而通過每次獲取令牌的個數增加或者放慢令牌的發放速度和降低整體資料處理速度,而漏桶不行,因為它的流出速率是固定的,程式處理速度也是固定的,

  • JVM有哪些回收演算法

    1)參考計數法 (2)復制演算法 (3)標記-清除演算法 (4)標記-整理演算法 (5)分代收集演算法

  • 垃圾收集器有哪些?

(1)Serial收集器 (2)ParNew 收集器 (3)Parallel Scavenge 收集器 (4)Serial Old收集器 (5)Parallel Old收集器 (6)CMS收集器 (7)G1收集器 (8)ZGC

  • 常見的分布式事務方案有哪些?

(1)兩階段提交方案 (2)eBay 事件佇列方案 (3)TCC 補償模式 (4)快取資料最終一致性

  • 運行時資料區域(記憶體模型)

(1)程式計數器:程式計數器是一塊較小的記憶體空間,它可以看作是當前執行緒所執行的位元組碼的行號指示器,在虛擬機的概念模型里,位元組碼解釋器作業時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、回圈、跳轉、例外處理、執行緒恢復等基礎功能都需要依賴這個計數器來完成,是執行緒私有”的記憶體, (2)Java虛擬機堆疊:與程式計數器一樣,Java虛擬機堆疊(Java Virtual Machine Stacks)也是執行緒私有的,它的生命周期與執行緒相同,虛擬機堆疊描述的是Java方法執行的記憶體模型:每個方法在執行的同時都會創建一個堆疊幀 ,用于存盤區域變數表、運算元堆疊、動態鏈接、方法出口等資訊,每一個方法從呼叫直至執行完成的程序,就對應著一個堆疊幀在虛擬機堆疊中入堆疊到出堆疊的程序, (3)本地方法堆疊:本地方法堆疊(Native Method Stack)與虛擬機堆疊所發揮的作用是非常相似的,它們之間的區別不過是虛擬機堆疊為虛擬機執行Java方法(也就是位元組碼)服務,而本地方法堆疊則為虛擬機使用到的Native方法服務, (4)Java堆:對于大多數應用來說,Java堆是Java虛擬機所管理的記憶體中最大的一塊,Java堆是被所有執行緒共享的一塊記憶體區域,在虛擬機啟動時創建,此記憶體區域的唯一目的就是存放物件實體,幾乎所有的物件實體都在這里分配記憶體, (5)方法區(1.8叫元資料):方法區與 Java 堆一樣,是各個執行緒共享的記憶體區域,它用于存盤已被虛擬機加載的類資訊、常量、靜態變數、即時編譯器編譯后的代碼等資料,

  • CAS操作ABA問題

如果在這段期間它的值曾經被改成了B,后來又被改回為A,那CAS操作就會誤認為它從來沒有被改變過,Java并發包為了解決這個問題,提供了一個帶有標記的原子參考類“AtomicStampedReference”,它可以通過控制變數值的版本來保證CAS的正確性

  • 為什么選擇B+樹作為索引結構?

(1)Hash索引:Hash索引底層是哈希表,哈希表是一種以key-value存盤資料的結構,所以多個資料在存盤關系上是完全沒有任何順序關系的,所以,對于區間查詢是無法直接通過索引查詢的,就需要全表掃描,所以,哈希索引只適用于等值查詢的場景,而B+ 樹是一種多路平衡查詢樹,所以他的節點是天然有序的(左子節點小于父節點、父節點小于右子節點),所以對于范圍查詢的時候不需要做全表掃描 (2)二叉查找樹:解決了排序的基本問題,但是由于無法保證平衡,可能退化為鏈表, (3)平衡二叉樹:通過旋轉解決了平衡的問題,但是旋轉操作效率太低, (4)紅黑樹:通過舍棄嚴格的平衡和引入紅黑節點,解決了 AVL旋轉效率過低的問題,但是在磁盤等場景下,樹仍然太高,IO次數太多, (5)B+樹:在B樹的基礎上,將非葉節點改造為不存盤資料純索引節點,進一步降低了樹的高度;此外將葉節點使用指標連接成鏈表,范圍查詢更加高效,

  • 臟讀和幻讀是什么?

(1)臟讀是指當一個事務正在訪問資料,并且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外一個事務也訪問了這個資料,然后使用了這個資料, (2)幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的資料進行了修改,這種修改涉及到了表中的全部資料行,同時,第二個事務也修改了這個表中的資料,這種修改是向表中插入一行新資料,那么,以后就會發生操作第一個事務的用戶發現表中還有沒有修改的資料行,就好像發生了幻覺一樣,

  • 如何解決Redis快取雪崩,快取穿透問題?

快取雪崩: (1)使用 Redis 高可用架構:使用 Redis 集群來保證 Redis 服務不會掛掉 (2)快取時間不一致,給快取的失效時間,加上一個隨機值,避免集體失效 (3)限流降級策略:有一定的備案,比如個性推薦服務不可用了,換成熱點資料推薦服務 快取穿透: (1)在介面做校驗 (2)存null值(快取擊穿加鎖) (3)布隆過濾器攔截: 將所有可能的查詢key 先映射到布隆過濾器中,查詢時先判斷key是否存在布隆過濾器中,存在才繼續向下執行,如果不存在,則直接回傳, 布隆過濾器將值進行多次哈希bit存盤,布隆過濾器說某個元素在,可能會被誤判,布隆過濾器說某個元素不在,那么一定不在,

  • Redis的持久化機制

redis為了保證效率,資料快取在了記憶體中,但是會周期性的把更新的資料寫入磁盤或者把修改操作寫入追加的記錄檔案中,以保證資料的持久化, Redis的持久化策略有兩種: (1)RDB:快照形式是直接把記憶體中的資料保存到一個dump的檔案中,定時保存,保存策略, 當Redis需要做持久化時,Redis會fork一個子行程,子行程將資料寫到磁盤上一個臨時RDB檔案中,當子行程完成寫臨時檔案后,將原來的RDB替換掉, (2)AOF:把所有的對Redis的服務器進行修改的命令都存到一個檔案里,命令的集合, 使用AOF做持久化,每一個寫命令都通過write函式追加到appendonly.aof中,aof的默認策略是每秒鐘fsync一次,在這種配置下,就算發生故障停機,也最多丟失一秒鐘的資料, 缺點是對于相同的資料集來說,AOF的檔案體積通常要大于RDB檔案的體積,根據所使用的fsync策略,AOF的速度可能會慢于RDB, Redis默認是快照RDB的持久化方式,

  • 三次握手

(1)第一次握手:建立連接時,客戶端發送syn包(syn=x)到服務器,并進入SYN_SENT狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers), (2)第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態; (3)第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手,

  • Kafka訊息是采用Pull模式,還是Push模式?

Kafka最初考慮的問題是,customer應該從brokes拉取訊息還是brokers將訊息推送到consumer,也就是pull還push,在這方面,Kafka遵循了一種大部分訊息系統共同的傳統的設計:producer將訊息推送到broker,consumer從broker拉取訊息,push模式下,當broker推送的速率遠大于consumer消費的速率時,consumer恐怕就要崩潰了,最終Kafka還是選取了傳統的pull模式,Pull模式的另外一個好處是consumer可以自主決定是否批量的從broker拉取資料,Pull有個缺點是,如果broker沒有可供消費的訊息,將導致consumer不斷在回圈中輪詢,直到新訊息到達,為了避免這點,Kafka有個引數可以讓consumer阻塞知道新訊息到達,

  • HashMap相關

(1)在jdk1.8之后,HashMap除了陣列+鏈表之外,參考了紅黑樹,需要說明對于參考了紅黑樹的 HashMap 如何put一個元素,以及鏈表是在何時轉化為紅黑樹的,比如,首先需要知道這個元素落在哪一個陣列里,獲取hashcode后并不是對陣列長度取余來確定的,而是高低位異或求與來得到的,這個地方首先得知道異或求與是做什么樣的運算的, (2)之后說一下在HashMap中的實作,比如hashcode無符號右移16位后和原hashcode做異或運算,這相當于把hashcode的高16位拿過來和hashcode的低16位做異或運算,因為無符號右移后前面說的16位都補零,這就是前面說的 "高低位異或“,進而是“求與”,和誰求與呢,和陣列長度減1 求與,說到這里起碼能夠證明你是看過原始碼的,接下來說說你的思考,比如我們知道對于hashmap 初始化容量決定了陣列大小,一般我們對于陣列這個初始容量的設定是有規律的,它應該是 2^n ,這個初始容量的設定影響了HashMap的效率,那又涉及到影響HashMap效率的主要因素,比如初始容量和負載因子,

  • 手寫一個基于懶漢式的雙重檢測的單例,

(1)單例有三個比較關鍵的點,一是私有構造方法,避免外部new出物件;二是保證唯一性;三是提供一個全域訪問點, (2)另外,懶漢式雙重檢測的實作方式 有三點需要注意的地方,一是全域訪問點必須是靜態的,外界使用可以通過類直接呼叫,二是在進入鎖之后還需要校驗,三是保存單例物件的私有變數一定要用volatile修飾,這個地方可以多說一些,比如volatile防止指令重排序,保證記憶體可見性(JVM層面和CPU層面可以分別說),

  • RPC原理

(1)為什么會出現RPC? RPC(Remote Procedure Call Protocol)——遠程程序呼叫協議, 一般來說,自己寫程式然后本地呼叫,這種程式的特點是服務的消費方和提供方,當我們進入公司時,面對的很可能就是成千上萬的服務提供方,這時候就需要使用RPC來進行遠程服務呼叫,RPC將原來的本地呼叫轉變為呼叫遠端的服務器上的方法,給系統的處理能力和吞吐量帶來了近似于無限制提升的可能, (2)RPC的組成 ①客戶端:服務的呼叫方 ②客戶端存根:存放服務端的地址訊息,再將客戶端的請求引數打包成網路訊息,③然后通過網路遠程發送給服務方, ④服務端:真正的服務提供者, ⑤服務端存根:接收客戶端發送過來的訊息,將訊息解包,并呼叫本地的方法,

  • Redis快取回識訓制

(1)資料過期: ①定時洗掉策略:Redis啟動一個定時器監控所有的key,一旦有過期的話就進行洗掉(遍歷所有key,非常耗費CPU) ②惰性洗掉策略:獲取key的時候判斷是否過期, 過期則進行洗掉 Redis采用的方式:①(隨機抓取一部分key進行檢測)+② (2)記憶體淘汰: ①noeviction:當記憶體不足以容納新寫入資料時,新寫入操作會報錯,(Redis 默認策略) ②allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的 Key,(LRU推薦使用) ③allkeys-random:當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個 Key, ④volatile-lru:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最近最少使用的 Key,這種情況一般是把 Redis 既當快取,又做持久化存盤的時候才用, ⑤volatile-random:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個 Key, ⑥volatile-ttl:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的 Key 優先移除,不推薦,如果沒有對應的鍵,則回退到noeviction策略,

  • Redis主從同步

(1)主從復制作用 ①資料冗余 ②故障恢復(服務冗余) ③負載均衡 ④讀寫分離(主節點寫操作、從節點讀操作) (2)主從復制程序 ①連接建立階段 步驟1:保存主節點資訊 步驟2:建立socket連接 步驟3:發送ping命令 步驟4:身份驗證 步驟5:發送從節點埠資訊 ②資料同步階段 從節點向主節點發送psync命令 根據主從節點當前狀態的不同,可以分為全量復制和部分復制 ③命令傳播階段 主從節點進入命令傳播階段;在這個階段主節點將自己執行的寫命令發送給從節點,從節點接收命令并執行,從而保證主從節點資料的一致性, (3)介紹全量復制和部分復制 ①全量復制:用于初次復制或其他無法進行部分復制的情況,將主節點中的所有資料都發送給從節點,是一個非常重型的操作, ②部分復制:用于網路中斷等情況后的復制,只將中斷期間主節點執行的寫命令發送給從節點,與全量復制相比更加高效,需要注意的是,如果網路中斷時間過長,導致主節點沒有能夠完整地保存中斷期間執行的寫命令,則無法進行部分復制,仍使用全量復制, (4)主從復制缺點:故障恢復無法自動化;寫操作無法負載均衡;存盤能力受到單機的限制,

  • 為什么會有哨兵機制?

在主從復制的基礎上,哨兵實作了自動化的故障恢復,

  • 哨兵機制作用?

(1)監控(Monitoring):哨兵會不斷地檢查主節點和從節點是否運作正常, (2)自動故障轉移(Automatic failover):當主節點不能正常作業時,哨兵會開始自動故障轉移操作,它會將失效主節點的其中一個從節點升級為新的主節點,并讓其他從節點改為復制新的主節點, (3)配置提供者(Configuration provider):客戶端在初始化時,通過連接哨兵來獲得當前Redis服務的主節點地址, (4)通知(Notification):哨兵可以將故障轉移的結果發送給客戶端,

  • 哨兵機制節點組成?

它由兩部分組成,哨兵節點和資料節點: (1)哨兵節點:哨兵系統由一個或多個哨兵節點組成,哨兵節點是特殊的redis節點,不存盤資料, (2)資料節點:主節點和從節點都是資料節點,

  • 哨兵機制原理?

(1)定時任務:每個哨兵節點維護了3個定時任務,定時任務的功能分別如下:通過向主從節點發送info命令獲取最新的主從結構;通過發布訂閱功能獲取其他哨兵節點的資訊;通過向其他節點發送ping命令進行心跳檢測,判斷是否下線, (2)主觀下線:在心跳檢測的定時任務中,如果其他節點超過一定時間沒有回復,哨兵節點就會將其進行主觀下線,顧名思義,主觀下線的意思是一個哨兵節點“主觀地”判斷下線;與主觀下線相對應的是客觀下線, (3)客觀下線:哨兵節點在對主節點進行主觀下線后,會通過sentinel is-master-down-by-addr命令詢問其他哨兵節點該主節點的狀態;如果判斷主節點下線的哨兵數量達到一定數值,則對該主節點進行客觀下線, (4)選舉領導者哨兵節點:當主節點被判斷客觀下線以后,各個哨兵節點會進行協商,選舉出一個領導者哨兵節點,并由該領導者節點對其進行故障轉移操作,監視該主節點的所有哨兵都有可能被選為領導者,選舉使用的演算法是Raft演算法;Raft演算法的基本思路是先到先得:即在一輪選舉中,哨兵A向B發送成為領導者的申請,如果B沒有同意過其他哨兵,則會同意A成為領導者,選舉的具體程序這里不做詳細描述,一般來說,哨兵選擇的程序很快,誰先完成客觀下線,一般就能成為領導者, (5)故障轉移:選舉出的領導者哨兵,開始進行故障轉移操作,該操作大體可以分為3個步驟: ①在從節點中選擇新的主節點:選擇的原則是,首先過濾掉不健康的從節點;然后選擇優先級最高的從節點(由slave-priority指定);如果優先級無法區分,則選擇復制偏移量最大的從節點;如果仍無法區分,則選擇runid最小的從節點, ②更新主從狀態:通過slaveof no one命令,讓選出來的從節點成為主節點;并通過slaveof命令讓其他節點成為其從節點, ③將已經下線的主節點(即6379)設定為新的主節點的從節點,當6379重新上線后,它會成為新的主節點的從節點,

  • 哨兵機制缺點

寫操作無法負載均衡;存盤能力受到單機的限制,(Redis集群解決了該情況)

  • Zookeeper鎖是如何實作的?

一般使用Curator進行使用Zookeeper鎖,例如有兩個客戶端A和客戶端B,首先A先在鎖節點下創建例如01子節點的鎖,然后再獲取節點資訊,發現自己的01節點排名第一,那么就獲得鎖, 客戶端B也需要獲取鎖,現在鎖節點下創建例如02的子節點,然后再獲取鎖節點資訊,發現鎖節點資訊為[01,02],并不排第一,因此獲取不到鎖,客戶端B會在他的順序節點的上一個順序節點加一個監聽器, 當客戶端A使用完鎖,洗掉01節點,客戶端B獲取到01洗掉的監聽,然后發現自己的02節點排名第一,那么就獲取到鎖,

  • JVM記憶體模型

(1)程式計數器:執行緒私有,用來程式跳轉,流程控制 (2)方法區(1.8叫元資料區):執行緒共享,用于存盤類資訊、常量、靜態變數等資訊 (3)Java虛擬機堆疊:執行緒私有,用于方法呼叫Java 虛擬機堆疊會出現兩種錯誤:StackOverFlowError 和 OutOfMemoryError (4)堆:執行緒私有,主要的記憶體區域,存盤物件實體,垃圾回收主要針對這一塊, (5)本地方法堆疊:執行緒共享,本地方法被執行的時候,在本地方法堆疊也會創建一個堆疊幀,用于存放該本地方法的區域變數表、運算元堆疊、動態鏈接、出口資訊,

  • G1和CMS垃圾回收器

G1和CMS垃圾回收器 (1)CMS收集器:是一種以獲取最短回收停頓時間為目標的收集器, 程序: ①初始標記:標記GC Roots能直接關聯到的物件,需要在safepoint位置暫停所有執行執行緒,---->STW ②并發標記:進行GC Roots Tracing,遍歷完從root可達的所有物件,該階段與作業執行緒并發執行, ③重新標記:修正并發標記期間因用戶程式繼續運作而導致標記產生表動的那一部分物件的標記記錄,需要在safepoint位置暫停所有執行執行緒,--->STW ④并發清除: 開啟用戶執行緒,同時 GC 執行緒開始對為標記的區域做清掃, 優點:并發收集、低停頓, 缺點: ①CMS收集器對CPU資源非常敏感, ②CMS收集器無法處理浮動垃圾(Floating Garbage), ③CMS收集器是基于標記-清除演算法,該演算法缺點都有:標記和清除效率低/產生大量不連續的記憶體碎片, ④停頓時間是不可預期的, (2)G1收集器:重新定義了堆空間,打破了原有的分代模型,將堆劃分為一個個區域,這么做的目的是在進行收集時不必在全堆范圍內進行,這是它最顯著的特點, 程序: ①初始標記:標記GC Roots 可以直接關聯的物件,該階段需要執行緒停頓但是耗時短,---->STW ②并發標記:尋找存活的物件,可以與其他程式并發執行,耗時較長, ③最終標記:并發標記期間用戶程式會導致標記記錄產生變動(好比一個阿姨一邊清理垃圾,另一個人一邊扔垃圾)虛擬機會將這段時間的變化記錄在Remembered Set Logs 中,最終標記階段會向Remembered Set合并并發標記階段的變化,這個階段需要執行緒停頓,也可以并發執行---->STW ④篩選回收:對每個Region的回收成本進行排序,按照用戶自定義的回收時間來制定回收計劃 優點: ①空間整合:G1使用Region獨立區域概念,G1利用的是標記復制法,不會產生垃圾碎片 ②分代收集:G1可以自己管理新生代和老年代 ③并行于并發:G1可以通過機器的多核來并發處理 STW停頓,減少停頓時間,并且可不停頓java執行緒執行GC動作,可通過并發方式讓GC和java程式同時執行, ④可預測停頓:G1除了追求停頓時間,還建立了可預測停頓時間模型,能讓制定的M毫秒時間片段內,消耗在垃圾回收器上的時間不超過N毫秒 缺點: G1 需要記憶集 (具體來說是卡表)來記錄新生代和老年代之間的參考關系,這種資料結構在 G1 中需要占用大量的記憶體,可能達到整個堆記憶體容量的 20% 甚至更多,而且 G1 中維護記憶集的成本較高,帶來了更高的執行負載,影響效率,

  • wait/await和sleep區別

(1)兩者最主要的區別在于:sleep 方法沒有釋放鎖,而 wait 方法釋放了鎖 , (2)兩者都可以暫停執行緒的執行, (3)wait 通常被用于執行緒間互動/通信,sleep 通常被用于暫停執行, (4)wait() 方法被呼叫后,執行緒不會自動蘇醒,需要別的執行緒呼叫同一個物件上的 notify() 或者 notifyAll() 方法,sleep() 方法執行完成后,執行緒會自動蘇醒,或者可以使用 wait(long timeout)超時后執行緒會自動蘇醒,

  • Redis的LRU過期策略的具體實作 Redis的LRU具體實作

用堆疊的形式會導致執行select *的時候大量非熱點資料占領頭部資料,所以需要改進, Redis每次按key獲取一個值的時候,都會更新value中的lru欄位為當前秒級別的時間戳,Redis初始的實作演算法很簡單,隨機從dict中取出五個key,淘汰一個lru欄位值最小的, 在3.0的時候,又改進了一版演算法,首先第一次隨機選取的key都會放入一個pool中(pool的大小為16),pool中的key是按lru大小順序排列的,接下來每次隨機選取的keylru值必須小于pool中最小的lru才會繼續放入,直到將pool放滿,放滿之后,每次如果有新的key需要放入,需要將pool中lru最大的一個key取出,淘汰的時候,直接從pool中選取一個lru最小的值然后將其淘汰,

  • 哪些物件可以作為GC Roots?

(1)虛擬機堆疊(堆疊幀中的本地變數表)中參考的物件, (2)方法區中類靜態屬性參考的物件, (3)方法區中常量參考的物件, (4)本地方法堆疊中JNI(即一般說的Native方法)參考的物件,

  • ConcurrentHashMap的資料結構

在JDK1.7版本中,ConcurrentHashMap維護了一個Segment陣列,Segment這個類繼承了重入鎖ReentrantLock,并且該類里面維護了一個 HashEntry<K,V>[] table陣列,在寫操作put,remove,擴容的時候,會對Segment加鎖,所以僅僅影響這個Segment,不同的Segment還是可以并發的,所以解決了執行緒的安全問題,同時又采用了分段鎖也提升了并發的效率,在JDK1.8版本中,ConcurrentHashMap摒棄了Segment的概念,而是直接用Node陣列+鏈表+紅黑樹的資料結構來實作,并發控制使用Synchronized和CAS來操作,整個看起來就像是優化過且執行緒安全的HashMap,

  • tcp和udp的優點與缺點

(1)TCP的優點: 可靠,穩定 TCP的可靠體現在TCP在傳遞資料之前,會有三次握手來建立連接,而且在資料傳遞時,有確認、視窗、重傳、擁塞控制機制,在資料傳完后,還會斷開連接用來節約系統資源, (2)TCP的缺點: 慢,效率低,占用系統資源高,易被攻擊 TCP在傳遞資料之前,要先建連接,這會消耗時間,而且在資料傳遞時,確認機制、重傳機制、擁塞控制機制等都會消耗大量的時間,而且要在每臺設備上維護所有的傳輸連接,事實上,每個連接都會占用系統的CPU、記憶體等硬體資源, 而且,因為TCP有確認機制、三次握手機制,這些也導致TCP容易被人利用,實作DOS、DDOS、CC等攻擊, (3)UDP的優點: 快,比TCP稍安全 UDP沒有TCP的握手、確認、視窗、重傳、擁塞控制等機制,UDP是一個無狀態的傳輸協議,所以它在傳遞資料時非常快,沒有TCP的這些機制,UDP較TCP被攻擊者利用的漏洞就要少一些,但UDP也是無法避免攻擊的,比如:UDP Flood攻擊…… (4)UDP的缺點: 不可靠,不穩定 因為UDP沒有TCP那些可靠的機制,在資料傳遞時,如果網路質量不好,就會很容易丟包, 基于上面的優缺點,那么: 什么時候應該使用TCP: 當對網路通訊質量有要求的時候,比如:整個資料要準確無誤的傳遞給對方,這往往用于一些要求可靠的應用,比如HTTP、HTTPS、FTP等傳輸檔案的協議,POP、SMTP等郵件傳輸的協議, 在日常生活中,常見使用TCP協議的應用如下: 瀏覽器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ檔案傳輸,什么時候應該使用UDP: 當對網路通訊質量要求不高的時候,要求網路通訊速度能盡量的快,這時就可以使用UDP, 比如,日常生活中,常見使用UDP協議的應用如下: QQ語音 QQ視頻 TFTP,

  • HashMap原理

(1)hashMap 是非執行緒安全的, hashMap 1.7的底層實作為陣列(table[])+鏈表(LinkList-->Entry),hashmap 1.8底層為陣列+鏈表/紅黑樹(當鏈表長度到達閾值TREEIFY_THRESHOLD(默認為8)時,會轉化為紅黑樹)

  • HashMap的put和resize的程序

(1)put程序: ①查看陣列是否需要初始化 ②根據key計算hashcode ③根據hashcode計算出桶位置 ④遍歷鏈表,查看key值與鏈表節點的key值是否相等,如果相等的話,那么進行覆寫舊值,并回傳舊值,1.8的話需要先查看鏈表長度是否達到閾值,如果達到閾值,先進行紅黑樹轉化然后再進行檢查擴容, ⑤新增的時候需要檢查是否需要擴容,需要擴容的話進行兩倍擴容,擴容完成后進行插入新值, (2)resize程序: resize擴容需要從四個方面來進行回答: ①什么時候觸發resize? 當容量超過當前容量(默認容量16)乘以負載因子(默認0.75)就會進行擴容,擴容大小為當前大小的兩倍(擴展問題,為啥是兩倍:通過限制length是一個2的冪數,h & (length-1)和h % length結果是一致的), ②resize是如何hash的:h & (length-1) ③resize是如何進行鏈表操作的:使用頭插法進行資料插入,每次新put的值放在頭部 ④并發操作下,鏈表是如何成環的:HashMap的環:若當前執行緒此時獲得ertry節點,但是被執行緒中斷無法繼續執行,此時執行緒二進入transfer函式,并把函式順利執行,此時新表中的某個位置有了節點,之后執行緒一獲得執行權繼續執行,因為并發transfer,所以兩者都是擴容的同一個鏈表,當執行緒一執行到e.next = new table[i] 的時候,由于執行緒二之前資料遷移的原因導致此時new table[i] 上就有ertry存在,所以執行緒一執行的時候,會將next節點,設定為自己,導致自己互相使用next參考對方,因此產生鏈表,導致死回圈,

  • 執行緒池有哪些型別

①FixedThreadPool:創建可重用固定執行緒數的執行緒池, ②SingleThreadPool:創建只有一個執行緒的執行緒池, ③CachedThreadPool:一個可根據需要創建新執行緒的執行緒池,如果現有執行緒沒有可用的,則創建一個新執行緒并添加到池中,如果有被使用完但是還沒銷毀的執行緒,就復用該執行緒,終止并從快取中移除那些已有 60 秒鐘未被使用的執行緒,因此,長時間保持空閑的執行緒池不會使用任何資源, ④ScheduledThreadPool:創建一個執行緒池,它可安排在給定延遲后運行命令或者定期地執行,

  • ConcurrentHashMap分段鎖原理

(1)ConcurrentHashMap采用了分段鎖技術,其中Segement繼承了RecentLock,當ConcurrentHashMap進行get、put操作時,均是同步的,各個Segement之間的get、put操作可以進行并發,即當一個執行緒訪問ConcurrentHashMap的Segement時,不會影響對其他Segement的訪問,

  • B-樹和B+樹區別

1)B-樹和B樹是一個概念,是多路搜索樹(相比于二叉搜索樹,IO次數更少),B-樹的特性: ①關鍵字集合分布在整顆樹中; ②任何一個關鍵字出現且只出現在一個結點中; ③搜索有可能在非葉子結點結束; ④其搜索性能等價于在關鍵字全集內做一次二分查找; ⑤其最底搜索性能為O(logN) (2)B+樹是B-樹的變體,也是一種多路搜索樹 B+的特性: ①所有關鍵字都出現在葉子結點的鏈表中(稠密索引),且鏈表中的關鍵字恰好是有序的; ②不可能在非葉子結點命中; ③非葉子結點相當于是葉子結點的索引(稀疏索引),葉子結點相當于是存盤(關鍵字)資料的資料層; ④更適合檔案索引系統; (3)B+樹的優勢: ①單一節點存盤更多的元素,使得查詢的IO次數更少, ②所有查詢都要查找到葉子節點,查詢性能穩定, ③所有葉子節點形成有序鏈表,便于范圍查詢,

  • Mysql資料庫索引原理

(1)MyISAM索引實作:MyISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的是資料記錄的地址, (2)Innodb索引實作: ①第一個重大區別是InnoDB的資料檔案本身就是索引檔案,MyISAM索引檔案和資料檔案是分離的,索引檔案僅保存資料記錄的地址,而在InnoDB中,表資料檔案本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的資料記錄,這個索引的key是資料表的主鍵,因此InnoDB表資料檔案本身就是主索引, ②第二個與MyISAM索引的不同是InnoDB的輔助索引data域存盤相應記錄主鍵的值而不是地址,換句話說,InnoDB的所有輔助索引都參考主鍵作為data域,

  • 組合索引怎么使用?最左匹配的原理,

1)組合索引怎么使用? 例如組合索引(a,b,c),組合索引的生效原則是: 從前往后依次使用生效,如果中間某個索引沒有使用,那么斷點前面(范圍值也算斷點,orderby不算斷點,用到索引)的索引部分起作用,斷點后面的索引沒有起作用; (2)最左匹配的原理:以最左邊的為起點任何連續的索引都能匹配上

  • Spring生命周期

Bean 的生命周期概括起來就是 4 個階段: (1)實體化(Instantiation) (2)屬性賦值(Populate) (3)初始化(Initialization) (4)銷毀(Destruction)

  • Spring幾種scope區別?

(1)singleton:Spring的IOC容器中只有一個實體bean,該值為scope的默認值 (2)prototype:每次getBean時都會創建一個新的實體 (3)request:每次請求都會創建一個物體bean (4)session:每次session請求時都會創建一個物體bean (5)globalsession:每個全域的HTTP Session,使用session定義的Bean都將產生一個新實體,

  • Spring AOP實作有哪幾種實作

介面代理和類代理會有什么區別? (1)Spring AOP有兩種實作,均為動態代理: ①JDK動態代理:基于反射進行動態代理,核心類是InvocationHandker類和Proxy類,被代理的類必須實作介面 ②CGLIB動態代理:被代理類無需實作介面,主要實作MethodInterceptor介面即可實作代理 (2)Spring AOP如果代理的類存在介面,優先使用JDK動態代理,否則使用CGLIB動態代理,
歡迎搜索關注本人與朋友共同開發的微信面經小程式【大廠面試助手】和公眾號【微瞰技術】

file
file

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/239428.html

標籤:其他

上一篇:Python實戰教程講解:爬起騰訊課堂視頻,優質課程隨你挑選

下一篇:大廠面試系列一些問題的解答

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more