InnoDB的行鎖java
(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同樣。
先更新數據庫,再刪緩存。數據庫的讀操做的速度遠快於寫操做的,因此髒數據很難出現。能夠對異步延時刪除策略,保證讀請求完成之後,再進行刪除操做
可能存儲的是整行數據,也有多是主鍵的值。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
(1)分佈式鎖+時間戳 (2)利用消息隊列
破壞「請求和保持」條件:讓進程在申請資源時,一次性申請全部須要用到的資源,不要一次一次來申請,當申請的資源有一些沒空,那就讓線程等待。不過這個方法比較浪費資源,進程可能常常處於飢餓狀態。還有一種方法是,要求進程在申請資源前,要釋放本身擁有的資源。 破壞「不可搶佔」條件:容許進程進行搶佔,方法一:若是去搶資源,被拒絕,就釋放本身的資源。方法二:操做系統容許搶,只要你優先級大,能夠搶到。 破壞「循環等待」條件:將系統中的全部資源統一編號,進程可在任什麼時候刻提出資源申請,但全部申請必須按照資源的編號順序提出(指定獲取鎖的順序,順序加鎖)
在開發高併發系統時有三把利器用來保護系統:緩存、降級和限流。 (1)緩存:緩存比較好理解,在大型高併發系統中,若是沒有緩存數據庫將分分鐘被爆,系統也會瞬間癱瘓。使用緩存不僅僅可以提高系統訪問速度、提升併發訪問量,也是保護數據庫、保護系統的有效方式。大型網站通常主要是「讀」,緩存的使用很容易被想到。在大型「寫」系統中,緩存也經常扮演者很是重要的角色。好比累積一些數據批量寫入,內存裏面的緩存隊列(生產消費),以及HBase寫數據的機制等等也都是經過緩存提高系統的吞吐量或者實現系統的保護措施。甚至消息中間件,你也能夠認爲是一種分佈式的數據緩存。 (2)降級:服務降級是當服務器壓力劇增的狀況下,根據當前業務狀況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行。降級每每會指定不一樣的級別,面臨不一樣的異常等級執行不一樣的處理。根據服務方式:能夠拒接服務,能夠延遲服務,也有時候能夠隨機服務。根據服務範圍:能夠砍掉某個功能,也能夠砍掉某些模塊。總之服務降級須要根據不一樣的業務需求採用不一樣的降級策略。主要的目的就是服務雖然有損可是總比沒有好。 (3)限流:限流能夠認爲服務降級的一種,限流就是限制系統的輸入和輸出流量已達到保護系統的目的。通常來講系統的吞吐量是能夠被測算的,爲了保證系統的穩定運行,一旦達到的須要限制的閾值,就須要限制流量並採起一些措施以完成限制流量的目的。好比:延遲處理,拒絕處理,或者部分拒絕處理等等。
常見的限流算法有計數器、漏桶和令牌桶算法。漏桶算法在分佈式環境中消息中間件或者Redis都是可選的方案。發放令牌的頻率增長能夠提高總體數據處理的速度,而經過每次獲取令牌的個數增長或者放慢令牌的發放速度和下降總體數據處理速度。而漏桶不行,由於它的流出速率是固定的,程序處理速度也是固定的。
JVM有哪些回收算法redis
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 堆同樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。
若是在這段期間它的值曾經被改爲了B,後來又被改回爲A,那CAS操做就會誤認爲它歷來沒有被改變過。Java併發包爲了解決這個問題,提供了一個帶有標記的原子引用類「AtomicStampedReference」,它能夠經過控制變量值的版原本保證CAS的正確性
(1)Hash索引:Hash索引底層是哈希表,哈希表是一種以key-value存儲數據的結構,因此多個數據在存儲關係上是徹底沒有任何順序關係的,因此,對於區間查詢是沒法直接經過索引查詢的,就須要全表掃描。因此,哈希索引只適用於等值查詢的場景。而B+ 樹是一種多路平衡查詢樹,因此他的節點是自然有序的(左子節點小於父節點、父節點小於右子節點),因此對於範圍查詢的時候不須要作全表掃描 (2)二叉查找樹:解決了排序的基本問題,可是因爲沒法保證平衡,可能退化爲鏈表。 (3)平衡二叉樹:經過旋轉解決了平衡的問題,可是旋轉操做效率過低。 (4)紅黑樹:經過捨棄嚴格的平衡和引入紅黑節點,解決了 AVL旋轉效率太低的問題,可是在磁盤等場景下,樹仍然過高,IO次數太多。 (5)B+樹:在B樹的基礎上,將非葉節點改造爲不存儲數據純索引節點,進一步下降了樹的高度;此外將葉節點使用指針鏈接成鏈表,範圍查詢更加高效。
(1)髒讀是指當一個事務正在訪問數據,而且對數據進行了修改。而這種修改尚未提交到數據庫中,這時,另一個事務也訪問了這個數據,而後使用了這個數據。 (2)幻讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到了表中的所有數據行。同時,第二個事務也修改了這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好像發生了幻覺同樣。
緩存雪崩: (1)使用 Redis 高可用架構:使用 Redis 集羣來保證 Redis 服務不會掛掉 (2)緩存時間不一致,給緩存的失效時間,加上一個隨機值,避免集體失效 (3)限流降級策略:有必定的備案,好比個性推薦服務不可用了,換成熱點數據推薦服務 緩存穿透: (1)在接口作校驗 (2)存null值(緩存擊穿加鎖) (3)布隆過濾器攔截: 將全部可能的查詢key 先映射到布隆過濾器中,查詢時先判斷key是否存在布隆過濾器中,存在才繼續向下執行,若是不存在,則直接返回。 布隆過濾器將值進行屢次哈希bit存儲,布隆過濾器說某個元素在,可能會被誤判。布隆過濾器說某個元素不在,那麼必定不在。
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最初考慮的問題是,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阻塞知道新消息到達。
(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層面能夠分別說)。
(1)爲何會出現RPC? RPC(Remote Procedure Call Protocol)——遠程過程調用協議。 通常來講,本身寫程序而後本地調用,這種程序的特色是服務的消費方和提供方。當咱們進入公司時,面對的極可能就是成千上萬的服務提供方,這時候就須要使用RPC來進行遠程服務調用。RPC將原來的本地調用轉變爲調用遠端的服務器上的方法,給系統的處理能力和吞吐量帶來了近似於無限制提高的可能。 (2)RPC的組成 ①客戶端:服務的調用方 ②客戶端存根:存放服務端的地址消息,再將客戶端的請求參數打包成網絡消息,③而後經過網絡遠程發送給服務方。 ④服務端:真正的服務提供者。 ⑤服務端存根:接收客戶端發送過來的消息,將消息解包,並調用本地的方法。
(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策略。
(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集羣解決了該狀況)
通常使用Curator進行使用Zookeeper鎖,例若有兩個客戶端A和客戶端B,首先A先在鎖節點下建立例如01子節點的鎖,而後再獲取節點信息,發現本身的01節點排名第一,那麼就得到鎖。 客戶端B也須要獲取鎖,如今鎖節點下建立例如02的子節點,而後再獲取鎖節點信息,發現鎖節點信息爲[01,02],並不排第一,所以獲取不到鎖,客戶端B會在他的順序節點的上一個順序節點加一個監聽器。 當客戶端A使用完鎖,刪除01節點,客戶端B獲取到01刪除的監聽,而後發現本身的02節點排名第一,那麼就獲取到鎖。
(1)程序計數器:線程私有,用來程序跳轉,流程控制 (2)方法區(1.8叫元數據區):線程共享,用於存儲類信息、常量、靜態變量等信息 (3)Java虛擬機棧:線程私有,用於方法調用Java 虛擬機棧會出現兩種錯誤:StackOverFlowError 和 OutOfMemoryError (4)堆:線程私有,主要的內存區域,存儲對象實例,垃圾回收主要針對這一塊。 (5)本地方法棧:線程共享,本地方法被執行的時候,在本地方法棧也會建立一個棧幀,用於存放該本地方法的局部變量表、操做數棧、動態連接、出口信息。
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 中維護記憶集的成本較高,帶來了更高的執行負載,影響效率。
(1)二者最主要的區別在於:sleep 方法沒有釋放鎖,而 wait 方法釋放了鎖 。 (2)二者均可以暫停線程的執行。 (3)wait 一般被用於線程間交互/通訊,sleep 一般被用於暫停執行。 (4)wait() 方法被調用後,線程不會自動甦醒,須要別的線程調用同一個對象上的 notify() 或者 notifyAll() 方法。sleep() 方法執行完成後,線程會自動甦醒。或者可使用 wait(long timeout)超時後線程會自動甦醒。
用棧的形式會致使執行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最小的值而後將其淘汰。
(1)虛擬機棧(棧幀中的本地變量表)中引用的對象。 (2)方法區中類靜態屬性引用的對象。 (3)方法區中常量引用的對象。 (4)本地方法棧中JNI(即通常說的Native方法)引用的對象。
在JDK1.7版本中,ConcurrentHashMap維護了一個Segment數組,Segment這個類繼承了重入鎖ReentrantLock,而且該類裏面維護了一個 HashEntry<K,V>[] table數組,在寫操做put,remove,擴容的時候,會對Segment加鎖,因此僅僅影響這個Segment,不一樣的Segment仍是能夠併發的,因此解決了線程的安全問題,同時又採用了分段鎖也提高了併發的效率。在JDK1.8版本中,ConcurrentHashMap摒棄了Segment的概念,而是直接用Node數組+鏈表+紅黑樹的數據結構來實現,併發控制使用Synchronized和CAS來操做,整個看起來就像是優化過且線程安全的HashMap。
(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。
(1)hashMap 是非線程安全的, hashMap 1.7的底層實現爲數組(table[])+鏈表(LinkList-->Entry),hashmap 1.8底層爲數組+鏈表/紅黑樹(當鏈表長度到達閾值TREEIFY_THRESHOLD(默認爲8)時,會轉化爲紅黑樹)
(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:建立一個線程池,它可安排在給定延遲後運行命令或者按期地執行。
(1)ConcurrentHashMap採用了分段鎖技術,其中Segement繼承了RecentLock,當ConcurrentHashMap進行get、put操做時,均是同步的。各個Segement之間的get、put操做能夠進行併發,即當一個線程訪問ConcurrentHashMap的Segement時,不會影響對其餘Segement的訪問。
1)B-樹和B樹是一個概念,是多路搜索樹(相比於二叉搜索樹,IO次數更少)。B-樹的特性: ①關鍵字集合分佈在整顆樹中; ②任何一個關鍵字出現且只出如今一個結點中; ③搜索有可能在非葉子結點結束; ④其搜索性能等價於在關鍵字全集內作一次二分查找; ⑤其最底搜索性能爲O(logN) (2)B+樹是B-樹的變體,也是一種多路搜索樹 B+的特性: ①全部關鍵字都出如今葉子結點的鏈表中(稠密索引),且鏈表中的關鍵字剛好是有序的; ②不可能在非葉子結點命中; ③非葉子結點至關因而葉子結點的索引(稀疏索引),葉子結點至關因而存儲(關鍵字)數據的數據層; ④更適合文件索引系統; (3)B+樹的優點: ①單一節點存儲更多的元素,使得查詢的IO次數更少。 ②全部查詢都要查找到葉子節點,查詢性能穩定。 ③全部葉子節點造成有序鏈表,便於範圍查詢。
(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)最左匹配的原理:以最左邊的爲起點任何連續的索引都能匹配上
Bean 的生命週期歸納起來就是 4 個階段: (1)實例化(Instantiation) (2)屬性賦值(Populate) (3)初始化(Initialization) (4)銷燬(Destruction)
(1)singleton:Spring的IOC容器中只有一個實例bean,該值爲scope的默認值 (2)prototype:每次getBean時都會建立一個新的實例 (3)request:每次請求都會建立一個實體bean (4)session:每次session請求時都會建立一個實體bean (5)globalsession:每一個全局的HTTP Session,使用session定義的Bean都將產生一個新實例。
接口代理和類代理會有什麼區別? (1)Spring AOP有兩種實現,均爲動態代理: ①JDK動態代理:基於反射進行動態代理,核心類是InvocationHandker類和Proxy類,被代理的類必須實現接口 ②CGLIB動態代理:被代理類無需實現接口,主要實現MethodInterceptor接口便可實現代理 (2)Spring AOP若是代理的類存在接口,優先使用JDK動態代理,不然使用CGLIB動態代理。 歡迎搜索關注本人與朋友共同開發的微信面經小程序【大廠面試助手】和公衆號【微瞰技術】