网易(杭州研究所)初面
覆蓋索引
如何實現索引覆蓋?
常見的方法是:將被查詢的字段,建立到聯合索引里去。
InnoDB聚集索引的葉子節點存儲行記錄,因此, InnoDB必須要有,且只有一個聚集索引
InnoDB普通索引的葉子節點存儲主鍵值。
舉個栗子,不妨設有表:
t(id PK, name KEY, sex, flag);
畫外音:id是聚集索引,name是普通索引。
表中有四條記錄:
1, shenjian, m, A
3, zhangsan, m, A
5, lisi, m, A
9, wangwu, f, B
兩個B+樹索引分別如上圖:
(1)id為PK,聚集索引,葉子節點存儲行記錄;
(2)name為KEY,普通索引,葉子節點存儲PK值,即id;
既然從普通索引無法直接定位行記錄,那普通索引的查詢過程是怎么樣的呢?
通常情況下,需要掃描兩遍索引樹。
例如:
select * from t where name=‘lisi’;
是如何執行的呢?
如粉紅色路徑,需要掃碼兩遍索引樹:
(1)先通過普通索引定位到主鍵值id=5;
(2)在通過聚集索引定位到行記錄;
這就是所謂的回表查詢,先定位主鍵值,再定位行記錄,它的性能較掃一遍索引樹更低。
當發起一個被索引覆蓋的查詢(也叫作索引覆蓋查詢)時,在EXPLAIN的Extra列可以看到“Using index”的信息
不是所有類型的索引都可以成為覆蓋索引。覆蓋索引必須要存儲索引的列,而哈希索引、空間索引和全文索引等都不存儲索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引
如何實現索引覆蓋?
select id,name,sex* from user where name=‘shenjian’;*
能夠命中name索引,索引葉子節點存儲了主鍵id,但sex字段必須回表查詢才能獲取到,不符合索引覆蓋,需要再次通過id值掃碼聚集索引獲取sex字段,效率會降低。
如果把(name)單列索引升級為聯合索引(name, sex)就不同了,可以避免回表。
參考:https://www.jianshu.com/p/8991cbca3854
ping實現以及對應協議
ping是定位網絡通不通的一個重要手段,是用來探測本機與網絡中另一臺主機之間是否可達的命令,如果兩臺主機之間ping不通,則表明這兩臺主機不能建立起連接。
ping命令是基于ICMP協議來工作的,ping命令會發送一份ICMP回顯請求報文給目標主機,并等待目標主機返回ICMP回顯應達,如果源主機在一定時間內收到了目標主機的應答,則表明兩臺主機間是連通的。
舉一個例子來描述ping命令工作的原理
1)假設有兩個主機,主機A(192.168.0.1)和主機B(192.168.0.2),現在我們要監測主機A和主機B之間網絡是否可達,那么我們在主機A上輸入命令:ping 192.168.0.2;
2)此時,ping命令會在主機A上構建一個 ICMP的請求數據包,然后 ICMP協議會將這個數據包以及目標IP(192.168.0.2)等信息一同交給IP層協議;
3)IP層協議得到這些信息后,將源地址(即本機IP)、目標地址(即目標IP:192.168.0.2)、再加上一些其它的控制信息,構建成一個IP數據包;
4)IP數據包構建完成后,還不夠,還需要加上MAC地址,因此,還需要通過ARP映射表找出目標IP所對應的MAC地址。當拿到了目標主機的MAC地址和本機MAC后,一并交給數據鏈路層,組裝成一個數據幀,依據以太網的介質訪問規則,將它們傳送出出去;
5)當主機B收到這個數據幀之后,會首先檢查它的目標MAC地址是不是本機,如果是就接收下來處理,接收之后會檢查這個數據幀,將數據幀中的IP數據包取出來,交給本機的IP層協議,然后IP層協議檢查完之后,再將ICMP數據包取出來交給ICMP協議處理,當這一步也處理完成之后,就會構建一個ICMP應答數據包,回發給主機A;
6)在一定的時間內,如果主機A收到了應答包,則說明它與主機B之間網絡可達,如果沒有收到,則說明網絡不可達。除了監測是否可達以外,還可以利用應答時間和發起時間之間的差值,計算出數據包的延遲耗時。
參考:https://www.cnblogs.com/mgd666/p/14389922.html
為什么要有Time-wait狀態(2MSL)
主動關閉的Socket端會進入TIME_WAIT狀態,并且持報文段最大生存時間續2MSL時間長度,MSL就是maximum segment lifetime(最大分節生命期),這是一個IP數據包能在互聯網上生存的最長時間,超過這個時間將在網絡中消失。MSL在RFC 1122上建議是2分鐘,而源自berkeley的TCP實現傳統上使用30秒,因而,TIME_WAIT狀態一般維持在1-4分鐘。
TIME_WAIT狀態存在的理由:
1)可靠地實現TCP全雙工連接的終止
在進行關閉連接四路握手協議時,最后的ACK是由主動關閉端發出的,如果這個最終的ACK丟失,服務器將重發最終的FIN,因此客戶端必須維護狀態信息允許它重發最終的ACK。如果不維持這個狀態信息,那么客戶端將響應RST分節,服務器將此分節解釋成一個錯誤(在java中會拋出connection reset的SocketException)。因而,要實現TCP全雙工連接的正常終止,必須處理終止序列四個分節中任何一個分節的丟失情況,主動關閉 的客戶端必須維持狀態信息進入TIME_WAIT狀態。
2)允許老的重復分節在網絡中消逝
TCP分節可能由于路由器異常而“迷途”,在迷途期間,TCP發送端可能因確認超時而重發這個分節,迷途的分節在路由器修復后也會被送到最終目的地,這個 原來的迷途分節就稱為lost duplicate。在關閉一個TCP連接后,馬上又重新建立起一個相同的IP地址和端口之間的TCP連接,后一個連接被稱為前一個連接的化身(incarnation),那么有可能出現這種情況,前一個連接的迷途重復分組在前一個連接終止后出現,從而被誤解成從屬于新的化身。為了避免這個情況,TCP不允許處于TIME_WAIT狀態的連接啟動一個新的化身,因為TIME_WAIT狀態持續2MSL,就可以保證當成功建立一個TCP連接的時候,來自連接先前化身的重復分組已經在網絡中消逝。
參考:https://blog.csdn.net/tennysonsky/article/details/48680197
TIMESTAMP和DATETIME的區別以及選擇
補充:什么是UTC?
答:協調世界時,又稱世界統一時間,世界標準時間,國際協調時間,簡稱UTC
不屬于任意時區
中國大陸、中國香港、中國澳門、中國臺灣、蒙古國、新加坡、馬來西亞、菲律賓、西澳大利亞州的時間與UTC的時差均為+8,也就是UTC+8。
時區(Time Zone)是地球上的區域使用同一個時間定義。1884年在華盛頓召開國際經度會議時,為了克服時間上的混亂,規定將全球劃分為24個時區。在中國采用首都北京所在地東八區的時間為全國統一使用時間。
對于MySQL中timestamp數據類型的特點,為什么選擇timestamp類型?
答:int類型占用4字節,datetime占用8字節,timestamp占用4字節;通常情況下在選擇表中列的數據類型時我們要選擇能滿足存儲需要的,最小的數據類型,在使用MySQL數據庫時有很多常見的誤解,其中使用int類型來保存日期數據會提高數據讀取的效率就是比較常見的一個誤解。顯然INT要比datetime類型小很多,同時MySQL又提供了兩個非常好用的函數FROM_UNIXTIME() 和UNIX_TIMESTAMP(),使用這兩個函數可以方便的在INT和DATETIME類型之間進行轉換,但是使用INT類型存儲時間也給我們帶來了不少的麻煩:
1.數據的可讀性比較差,我們在查看數據時不能直觀的看出時間列中記錄的一串整數所代表的時間
2.每次進行顯示時都要通過函數進行轉換,增加了數據使用的復雜成度。
那有沒有什么更好的方法來存儲日期數據呢?這就要用到我們標題中所說到的timestamp類型了,timestamp類型的特點如下:
1.存儲占用 4個字節,以年月日小時分秒的日期型式顯示
2.存儲范圍’1970-01-01 00:00:01’ to ‘2038-01-19 03:14:07’.
3.以UTC時區進行存儲,但是以系統當前時間進行顯示
4.可以在insert和update時把值自動更新為當前時間
由以上特點可以知道,timestamp存儲占用的空間和INT類型相同,實際上timestamp類型的數據在存儲時就是被保存成INT類型的數據來存儲的,這和我們使用INT來存儲日期時間數據可以說是完全一樣的。由于同樣是使用INT類型來保存數據,所以和INT類型一樣其存儲的時間范圍也是有限制的,
**這一點大家一定要注意,超過了這個范圍的日期數據建議大家使用datetime類型來保存。**另外timestamp數據存儲時是以UTC時區來保存的,在顯示時MySQL會自動的把數據轉換為當前連接所對應時間來顯示。
可見,使用timestamp來存儲日期時間數據不但保證了數據類型的大小同INT類型一樣,同時可以顯示為日期時間格式,這在給我們使用數據帶來了很多的方便。所以強烈建議大家,使用timestamp類型來存儲日期數據而不要再使用INT類型了。(轉自:https://www.imooc.com/article/16158)
四次揮手相對三次握手多一次?
因為:客戶端單方面無數據發送認為可以結束了,但是服務端不一定沒有數據發送,所以服務端要將確信信息和自身發起斷開分作兩步
有了 IP 地址,為什么還要用 MAC 地址?
有了 IP 地址,為什么還要用 MAC 地址?
是TCP/IP協議的一部分。利用“ping”命令可以檢查網絡是否通暢或者網絡連接速度,很好地分析和判定網絡故障。
Ping發送一個ICMP(Internet Control Messages Protocol),即因特網信報控制協議;接收端回聲消息給目的地并報告是否收到所希望的ICMPecho (ICMP回聲應答)。它的原理是:利用網絡上機器IP地址的唯一性,給目標IP地址發送一個數據包,通過對方回復的數據包來確定兩臺網絡機器是否連接相通,時延是多少。
進程間的通信
管道pipe:管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。
命名管道FIFO:有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
消息隊列MessageQueue:消息隊列是由消息的鏈表,存放在內核中并由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
共享存儲SharedMemory:共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。
信號量Semaphore:信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
套接字Socket:套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同及其間的進程通信。
信號 ( sinal ) : 信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經發生。
補充:線程間的通信方式
鎖機制:包括互斥鎖、條件變量、讀寫鎖
互斥鎖提供了以排他方式防止數據結構被并發修改的方法。
讀寫鎖允許多個線程同時讀共享數據,而對寫操作是互斥的。
條件變量可以以原子的方式阻塞進程,直到某個特定條件為真為止。對條件的測試是在互斥鎖的保護下進行的。條件變量始終與互斥鎖一起使用。
信號量機制(Semaphore):包括無名線程信號量和命名線程信號量
信號機制(Signal):類似進程間的信號處理
線程間的通信目的主要是用于線程同步,所以線程沒有像進程通信中的用于數據交換的通信機制。
原文鏈接:https://blog.csdn.net/weixin_41903587/article/details/109529691
補充:堆和棧的區別
1.管理方式不同。棧由操作系統自動分配釋放,不需要我們手動控制;堆的申請和釋放工作由程序員控制,因此容易產生內存泄漏。
2.空間大小不同。棧的大小一般只有8~10M,而堆有幾個G。
3.生長方向不同。棧的生長方向向下,內存的地址由高到低,堆的生長方向向上,內存的地址由低到高。
4.分配方式不同。堆時動態分配的;棧有兩種分配方式:靜態分配和動態分配。靜態分配是由操作系統完成,比如局部變量的分配。動態分配由malloc函數進行分配,但是棧的動態分配和堆是不同的,棧的動態分配是由操作系統進行釋放,不需要我們手動釋放。
5.分配效率不同。棧由操作系統自動分配,會在硬件層級對棧提供支持。分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是由C/C++提供的庫函數或運算符來完成申請與管理,實現機制比較復雜,頻繁的內存申請容易產生內存碎片。顯然,堆的效率比棧低得多。
由此可見,堆和棧相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的內存碎片。棧相比于堆,在程序中應用較為廣泛,最常見的函數調用過程由棧來實現,函數返回地址、實參和局部變量都采用棧的方式存放。雖然棧有眾多的好處,但是和堆相比不是那么靈活,有時候分配大量的內存空間任然需要用堆。總之無論是堆還是棧,在內存使用時都要防止非法越界。
參考:https://blog.csdn.net/tangya3158613488/article/details/88845180
線程并行理解
用多線程只有一個目的,那就是更好的利用cpu的資源,因為所有的多線程代碼都可以用單線程來實現。說這個話其實只有一半對,因為反應“多角色”的程序代碼,最起碼每個角色要給他一個線程吧,否則連實際場景都無法模擬,當然也沒法說能用單線程來實現:比如最常見的“生產者,消費者模型”。
很多人都對其中的一些概念不夠明確,如同步、并發等等,讓我們先建立一個數據字典,以免產生誤會。
多線程:指的是這個程序(一個進程)運行時產生了不止一個線程
并行與并發:
并行:多個cpu實例或者多臺機器同時執行一段處理邏輯,是真正的同時。
并發:通過cpu調度算法,讓用戶看上去同時執行,實際上從cpu操作層面不是真正的同時。并發往往在場景中有公用的資源,那么針對這個公用的資源往往產生瓶頸,我們會用TPS或者QPS來反應這個系統的處理能力。
并發與并行
線程安全:經常用來描繪一段代碼。指在并發的情況之下,該代碼經過多線程使用,線程的調度順序不影響任何結果。這個時候使用多線程,我們只需要關注系統的內存,cpu是不是夠用即可。
同步:Java中的同步指的是通過人為的控制和調度,保證共享資源的多線程訪問成為線程安全,來保證結果的準確。如上面的代碼簡單加入@synchronized關鍵字。在保證結果準確的同時,提高性能,才是優秀的程序。線程安全的優先級高于性能。
多態
面向對象編程有三大特性:封裝、繼承、多態。封裝隱藏了類的內部實現機制,可以在不影響使用的情況下改變類的內部結構,同時也保護了數據。對外界而已它的內部細節是隱藏的,暴露給外界的只是它的訪問方法。
繼承是為了重用父類代碼。兩個類若存在IS-A的關系就可以使用繼承。,同時繼承也為實現多態做了鋪墊。那么什么是多態呢?多態的實現機制又是什么?請看我一一為你揭開:
所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時并不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。因為在程序運行時才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實現上,從而導致該引用調用的具體方法隨之改變,即不修改程序代碼就可以改變程序運行時所綁定的具體代碼,讓程序可以選擇多個運行狀態,這就是多態性。
程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時并不確定,而是在程序運行期間才確定
基本數據類型和應用數據類型
Java中的數據類型分為兩大類,基本數據類型和引用數據類型。
1、基本數據類型
基本數據類型只有8種,可按照如下分類
①整數類型:long、int、short、byte
②浮點類型:float、double
③字符類型:char
④布爾類型:boolean
2、引用數據類型
引用數據類型非常多,大致包括:
類、 接口類型、 數組類型、 枚舉類型、 注解類型、 字符串型
例如,String類型就是引用類型。
簡單來說,所有的非基本數據類型都是引用數據類型。
二、基本數據類型和引用數據類型的區別
1、存儲位置
基本變量類型
在方法中定義的非全局基本數據類型變量的具體內容是存儲在棧中的
引用變量類型
只要是引用數據類型變量,其具體內容都是存放在堆中的,而棧中存放的是其具體內容所在內存的地址
ps:通過變量地址可以找到變量的具體內容,就如同通過房間號可以找到房間一般
2、傳遞方式
基本變量類型
在方法中定義的非全局基本數據類型變量,調用方法時作為參數是按數值傳遞的
引用變量類型
引用數據類型變量,調用方法時作為參數是按引用傳遞的,傳遞的是引用的副本
調用時為temp在棧中開辟新空間,并指向book的具體內容,方法執行完畢后temp在棧中的內存被釋放掉
參考:https://www.cnblogs.com/maskwolf/p/9972982.html
Java垃圾回收機制
為什么要進行垃圾回收?
隨著程序的運行,內存中存在的實例對象、變量等信息占據的內存越來越多,如果不及時進行垃圾回收,必然會帶來程序性能的下降,甚至會因為可用內存不足造成一些不必要的系統異常。
哪些“垃圾”需要回收?
如果某個對象已經不存在任何引用,那么它可以被回收。
什么時候進行垃圾回收?
引用計數算法
每個對象添加一個引用計數器,每被引用一次,計數器加1,失去引用,計數器減1,當計數器在一段時間內保持為0時,該對象就認為是可以被回收得了。(在JDK1.2之前,使用的是該算法)
缺點:當兩個對象A、B相互引用的時候,當其他所有的引用都消失之后,A和B還有一個相互引用,此時計數器各為1,而實際上這兩個對象都已經沒有額外的引用了,已經是垃圾了。但是卻不會被回收
可達性分析算法
該算法是從離散數學中的圖論引入的,程序把所有的引用關系看作一張圖,從一個節點GC ROOT 開始,尋找對應的引用節點,找到這個節點以后,繼續尋找這個節點的引用節點,當所有的引用節點尋找完畢之后,剩余的節點則被認為是沒有被引用到的節點,即無用的節點
目前java 中可作為GC Root 的對象有:
虛擬機棧中引用的對象(本地變量表)
方法區中靜態屬性引用的對象
方法區中常量引用的對象
本地方法棧中引用的對象(Native Object)
引用計數法
給對象添加一引用計數器,被引用一次計數器值就加 1;當引用失效時,計數器值就減 1;計數器為 0 時,對象就是不可能再被使用的,簡單高效,缺點是無法解決對象之間相互循環引用的問題。
可達性分析算法
通過一系列的稱為 “GC Roots” 的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當一個對象到 GC Roots 沒有任何引用鏈相連時,則證明此對象是不可用的。此算法解決了上述循環引用的問題。
引用的分類
JDK 1.2之后,對引用進行了擴充,引入了強、軟、若、虛四種引用,被標記為這四種引用的對象,在GC時分別有不同的意義:
強引用(Strong Reference)
就是為剛被new出來的對象所加的引用,它的特點就是,永遠不會被GC,除非顯示的設置null,才會GC。代碼如下:
Object ojb = new Object();
軟引用(Soft Reference)
非必須引用,內存溢出之前進行回收。如果JVM內存并不緊張,這類對象可以不被回收,如果內存緊張,則會被回收。此處有一個問題,既然被引用為軟引用的對象可以回收,為什么不去回收呢?其實我們知道,Java中是存在緩存機制的,就拿字面量緩存來說,有些時候,緩存的對象就是當前可有可無的,只是留在內存中如果還有需要,則不需要重新分配內存即可使用,因此,這些對象即可被引用為軟引用,方便使用,提高程序性能。代碼如下:
Object obj = new Object();
SoftReference sf = new SoftReference(obj);
obj =null;
sf.get();//有時候會返回null
這時候sf是對obj的一個軟引用,通過sf.get()方法可以取到這個對象,當然,當這個對象被標記為需要回收的對象時,則返回null;
弱引用(Weak Reference)
第二次垃圾回收時回收。代碼如下:
Object obj = new Object();
WeakReference wf = new WeakReference(obj);
obj =null;
wf.get();//有時候會返回null
wf.isEnQueued();//返回是否被垃圾回收器標記為即將回收的垃圾
弱引用是在第二次垃圾回收時回收,短時間內通過弱引用取對應的數據,可以取到,當執行過第二次垃圾回收時,將返回null。
弱引用主要用于監控對象是否已經被垃圾回收器標記為即將回收的垃圾,可以通過弱引用的isEnQueued方法返回對象是否被垃圾回收器
虛引用(Phantom Reference)
垃圾回收時回收,無法通過引用取到對象值。代碼如下
Object obj = new Object();
PhantomReference pf = new PhantomReference(obj);
obj=null;
pf.get();//永遠返回null
pf.isEnQueued();//返回從內存中已經刪除
虛引用是每次垃圾回收的時候都會被回收,通過虛引用的get方法永遠獲取到的數據為null,因此也被成為幽靈引用。虛引用主要用于檢測對象是否已經從內存中刪除。
擴展:如果一個對象的引用有多個,怎么通過可達性確定回收周期呢?兩個原則:
單條引用鏈上,由最弱的一個引用類型決定
多條引用鏈上,由最強的一個引用類型決定
這個想想其實還是很好理解的。
原文鏈接:https://blog.csdn.net/w372426096/article/details/81360083
如何垃圾回收
內存主要被分為三塊,新生代、舊生代、持久代。三代的特點不同,造就了他們所用的GC算法不同,新生代適合那些生命周期較短,頻繁創建及銷毀的對象,舊生代適合生命周期相對較長的對象,持久代在Sun HotSpot中就是指方法區(有些JVM中根本就沒有持久代這中說法)。首先介紹下新生代、舊生代、持久代的概念及特點:
新生代:New Generation或者Young Generation。上面大致分為Eden區和Survivor區,Survivor區又分為大小相同的兩部分:FromSpace 和ToSpace。新建的對象都是用新生代分配內存,Eden空間不足的時候,會把存活的對象轉移到Survivor中,新生代的大小可以由-Xmn來控制,也可以用-XX:SurvivorRatio來控制Eden和Survivor的比例.
舊生代:Old Generation。用于存放新生代中經過多次垃圾回收仍然存活的對象,例如緩存對象。舊生代占用大小為-Xmx值減去-Xmn對應的值。
持久代:Permanent Generation。在Sun的JVM中就是方法區的意思,盡管有些JVM大多沒有這一代。主要存放常量及類的一些信息默認最小值為16MB,最大值為64MB,可通過-XX:PermSize及-XX:MaxPermSize來設置最小值和最大值。
常見的GC算法:
標記-清除算法(Mark-Sweep)
就是分為標記和清除兩個階段進行處理內存中的對象缺點:
效率問題,標記和清除兩個過程的效率都不高;
空間問題,標記清除之后會產生大量不連續的內存碎片,空間碎片太多可能會導致以后在程序運行過程中需要分配較大對象時,無法找到足夠的連續內存而不得不提前觸發另一次垃圾收集動作。
復制算法(Copying)
將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。
當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然后再把已使用過的內存空間一次清理掉。反復去交換兩個內存的角色,完成垃圾收集
java中新生代的from和to空間就是使用這個算法
優點:這樣使得每次都是對整個半區進行內存回收,內存分配時也就不用考慮內存碎片等。復雜情況,只要移動堆頂指針,按順序分配內存即可,實現簡單,運行高效。只是這種算法的代價是將內存縮小為了原來的一半,未免太高了一點。
缺點:復制收集算法在對象存活率較高時就要進行較多的復制操作,效率將會變低(所以eden區沒有采用這個算法)
分代收集算法(Generational Collection)
1、根據對象存活周期的不同將內存劃分為幾塊。
2、一般是把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。
3、在新生代中,每次垃圾收集時都發現有大批對象死去(回收頻率很高),只有少量存活,那就選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。
其中,新生代又細分為三個區:Eden,From Survivor,ToSurviver,比例是8:1:1
4、老年代中因為對象存活率高、沒有額外空間對它進行分配擔保,就必須使用“標記—清理”或者“標記—整理”算法來進行回收。
分區算法
其主要就是將整個內存分為N個多小的獨立空間,每個小空間都可以獨立使用,這樣細粒度的控制一次回收都少個小空間和那些個小空間,而不是對整個空間進行GC,從而提升性能,并減少GC的停頓時間。
GC算法優劣標準
評價一個垃圾收集GC算法的兩個標準
吞吐量(throughput)越高算法越好
暫停時間(pause times)越短算法越好
停頓
一個時間段內應用程序線程讓GC線程執行而完全暫停。
垃圾回收器的任務是識別和回收垃圾對象進行內存清理,為了讓垃圾回收器可以高效的執行,大部分情況下,會要求系統進入一個停頓的狀態。停頓的目的是終止所有應用線程,只有這樣系統才不會有新的垃圾產生,同時停頓保證了系統狀態在某一個瞬間的一致性,也有益于更好地標記垃圾對象,因此垃圾回收時,都會產生應用程序的停頓
原文鏈接:https://blog.csdn.net/w372426096/article/details/81360083
總結
以上是生活随笔為你收集整理的网易(杭州研究所)初面的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大连商务英语百家外语商务英语与普通英语有
- 下一篇: 发生身份验证错误,要求的函数不受支持