




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Java的數(shù)據(jù)結(jié)構(gòu)相關(guān)的類實(shí)現(xiàn)原理List接口 List是有序的Collection,使用此接口能夠精確的控制每個(gè)元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似于數(shù)組下標(biāo))來訪問List中的元素,這類似于Java的數(shù)組。 和下面要提到的Set不同,List允許有相同的元素。 除了具有Collection接口必備的iterator()方法外,List還提供一個(gè)listIterator()方法,返回一個(gè)ListIterator接口,和標(biāo)準(zhǔn)的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設(shè)定元素,還能向前
2、或向后遍歷。 實(shí)現(xiàn)List接口的常用類有LinkedList,ArrayList,Vector和Stack。 LinkedListList 接口的鏈接列表實(shí)現(xiàn)。實(shí)現(xiàn)所有可選的列表操作,并且允許所有元素(包括 null)。除了實(shí)現(xiàn) List 接口外,LinkedList 類還為在列表的開頭及結(jié)尾 get、remove 和 insert 元素提供了統(tǒng)一的命名方法。這些操作允許將鏈接列表用作堆棧、隊(duì)列或雙端隊(duì)列。此類實(shí)現(xiàn) Deque 接口,為 add、poll&
3、#160;提供先進(jìn)先出隊(duì)列操作,以及其他堆棧和雙端隊(duì)列操作。所有操作都是按照雙重鏈接列表的需要執(zhí)行的。在列表中編索引的操作將從開頭或結(jié)尾遍歷列表(從靠近指定索引的一端)。注意,此實(shí)現(xiàn)不是同步的。如果多個(gè)線程同時(shí)訪問一個(gè)鏈接列表,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了該列表,則它必須 保持外部同步。(結(jié)構(gòu)修改指添加或刪除一個(gè)或多個(gè)元素的任何操作;僅設(shè)置元素的值不是結(jié)構(gòu)修改。)這一般通過對(duì)自然封裝該列表的對(duì)象進(jìn)行同步操作來完成。如果不存在這樣的對(duì)象,則應(yīng)該使用 Collections.synchronizedList 方法來“包裝”該列表。最好在創(chuàng)建時(shí)完成這一操作,以防止對(duì)
4、列表進(jìn)行意外的不同步訪問,如下所示: List list = Collections.synchronizedList(new LinkedList(.);此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗 的:在迭代器創(chuàng)建之后,如果從結(jié)構(gòu)上對(duì)列表進(jìn)行修改,除非通過迭代器自身的remove
5、 或 add 方法,其他任何時(shí)間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對(duì)并發(fā)的修改,迭代器很快就會(huì)完全失敗,而不冒將來不確定的時(shí)間任意發(fā)生不確定行為的風(fēng)險(xiǎn)。注意,迭代器的快速失敗行為不能得到保證,一般來說,存在不同步的并發(fā)修改時(shí),不可能作出任何硬性保證。快速失敗迭代器盡最大努力拋出ConcurrentModificationException。因此,編寫依賴于此異常的程序的方式是錯(cuò)誤的,正確做法是:迭代器的快速失敗行為應(yīng)該僅用于檢測程序錯(cuò)誤。ArrayList Ar
6、rayList是List接口的可變數(shù)組的實(shí)現(xiàn)。實(shí)現(xiàn)了所有可選列表操作,并允許包括 null 在內(nèi)的所有元素。除了實(shí)現(xiàn) List 接口外,此類還提供一些方法來操作內(nèi)部用來存儲(chǔ)列表的數(shù)組的大小。 每個(gè)ArrayList實(shí)例都有一個(gè)容量,該容量是指用來存儲(chǔ)列表元素的數(shù)組的大小。它總是至少等于列表的大小。隨著向ArrayList中不斷添加元素,其容量也自動(dòng)增長。自動(dòng)增長會(huì)帶來數(shù)據(jù)向新數(shù)組的重新拷貝,因此,如果可預(yù)知數(shù)據(jù)量的多少,可在構(gòu)造ArrayList時(shí)指定其容量。在添加大量元素前,應(yīng)用程序也可以使用ensureCapacity操作來增加ArrayList實(shí)例的容量,這可以減
7、少遞增式再分配的數(shù)量。 注意,此實(shí)現(xiàn)不是同步的。如果多個(gè)線程同時(shí)訪問一個(gè)ArrayList實(shí)例,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了列表,那么它必須保持外部同步。HashMap HashMap是基于哈希表的Map接口的非同步實(shí)現(xiàn)。此實(shí)現(xiàn)提供所有可選的映射操作,并允許使用null值和null鍵。此類不保證映射的順序,特別是它不保證該順序恒久不變。HashMap也不例外。HashMap實(shí)際上是一個(gè)“鏈表的數(shù)組”的數(shù)據(jù)結(jié)構(gòu),每個(gè)元素存放鏈表頭結(jié)點(diǎn)的數(shù)組,即數(shù)組和鏈表的結(jié)合體。HashMap底層就是一個(gè)數(shù)組結(jié)構(gòu),數(shù)組中的每一
8、項(xiàng)又是一個(gè)鏈表。當(dāng)新建一個(gè)HashMap的時(shí)候,就會(huì)初始化一個(gè)數(shù)組。當(dāng)我們往HashMap中put元素的時(shí)候,先根據(jù)key的hashCode重新計(jì)算hash值,根據(jù)hash值得到這個(gè)元素在數(shù)組中的位置(即下標(biāo)),如果數(shù)組該位置上已經(jīng)存放有其他元素了,那么在這個(gè)位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。如果數(shù)組該位置上沒有元素,就直接將該元素放到此數(shù)組中的該位置上。當(dāng)系統(tǒng)決定存儲(chǔ)HashMap中的key-value對(duì)時(shí),完全沒有考慮Entry中的value,僅僅只是根據(jù)key來計(jì)算并決定每個(gè)Entry的存儲(chǔ)位置。我們完全可以把 Map 集合中的
9、160;value 當(dāng)成 key 的附屬,當(dāng)系統(tǒng)決定了 key 的存儲(chǔ)位置之后,value 隨之保存在那里即可。在HashMap中要找到某個(gè)元素,需要根據(jù)key的hash值來求得對(duì)應(yīng)數(shù)組中的位置。如何計(jì)算這個(gè)位置就是hash算法。前面說過HashMap的數(shù)據(jù)結(jié)構(gòu)是數(shù)組和鏈表的結(jié)合,所以我們當(dāng)然希望這個(gè)HashMap里面的 元素位置盡量的分布均勻些,盡量使得每個(gè)位置上的元素?cái)?shù)量只有一個(gè),那么當(dāng)我們用hash算法求得這個(gè)位置的時(shí)候,馬上就可以知道對(duì)應(yīng)位置的元素就是我們要的,而不用再去遍歷鏈表,這樣就大大優(yōu)化了查詢的效率。歸納起來
10、簡單地說,HashMap 在底層將 key-value 當(dāng)成一個(gè)整體進(jìn)行處理,這個(gè)整體就是一個(gè) Entry 對(duì)象。HashMap 底層采用一個(gè) Entry 數(shù)組來保存所有的 key-value 對(duì),當(dāng)需要存儲(chǔ)一個(gè) Entry 對(duì)象時(shí),會(huì)根據(jù)hash算法來決定其在數(shù)組中的存儲(chǔ)位置,在根據(jù)equals方法決定其在該數(shù)組位置上的鏈表中的存儲(chǔ)位置;當(dāng)需要取出一個(gè)Entry時(shí),也會(huì)根據(jù)hash算法找到其在數(shù)組中的存儲(chǔ)位置,再根據(jù)equals方法從該位置上的鏈表中取出該Entry。Has
11、hSet HashSet實(shí)現(xiàn)Set接口,由哈希表(實(shí)際上是一個(gè)HashMap實(shí)例)支持。它不保證set 的迭代順序;特別是它不保證該順序恒久不變。此類允許使用null元素。HashSet實(shí)現(xiàn)Set接口,由哈希表(實(shí)際上是一個(gè)HashMap實(shí)例)支持。它不保證set 的迭代順序;特別是它不保證該順序恒久不變。此類允許使用null元素。HashSet中不允許有重復(fù)元素,這是因?yàn)镠ashSet是基于HashMap實(shí)現(xiàn)的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是統(tǒng)一的一個(gè)private static final Object PRE
12、SENT = new Object();。HashSet跟HashMap一樣,都是一個(gè)存放鏈表的數(shù)組。HashSet中add方法調(diào)用的是底層HashMap中的put()方法,而如果是在HashMap中調(diào)用put,首先會(huì)判斷key是否存在,如果key存在則修改value值,如果key不存在這插入這個(gè)key-value。而在set中,因?yàn)関alue值沒有用,也就不存在修改value值的說法,因此往HashSet中添加元素,首先判斷元素(也就是key)是否存在,如果不存在這插入,如果存在著不插入,這樣HashSet中就不存在重復(fù)值。HashMap是不是有序的HashSet 和Hashmap分別是Se
13、t接口和Map接口的實(shí)現(xiàn)類,運(yùn)用哈希算法來存取元素,也就是它們中的對(duì)象不按特定方式排序; 有沒有有順序的Map實(shí)現(xiàn)類TreeMap和LinkedHashMapLinkedHashMapTreeMap?你覺得它們兩個(gè)哪個(gè)的有序?qū)崿F(xiàn)比較好?LinkedHashMap保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí),先得到的記錄肯定是先插入的.也可以在構(gòu)造時(shí)用帶參數(shù),按照應(yīng)用次數(shù)排序。在遍歷的時(shí)候會(huì)比HashMap慢,不過有種情況例外,當(dāng)HashMap容量很大,實(shí)際數(shù)據(jù)較少時(shí),遍歷起來可能會(huì)比LinkedHashMap慢,因?yàn)長inkedHashMap的遍歷速度只
14、和實(shí)際數(shù)據(jù)有關(guān),和容量無關(guān),而HashMap的遍歷速度和他的容量有關(guān)。 TreeMap實(shí)現(xiàn)SortMap接口,能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按鍵值的升序排序,也可以指定排序的比較器,當(dāng)用Iterator 遍歷TreeMap時(shí),得到的記錄是排過序的。TreeMap取出來的是排序后的鍵值對(duì)。但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會(huì)更好。LinkedHashMap 是HashMap的一個(gè)子類,如果需要輸出的順序和輸入的相同,那么用LinkedHashMap可以實(shí)現(xiàn),它還可以按讀取順序來排列,像連接池中可以應(yīng)用。你覺得還有沒有比它更好或者更高效的實(shí)現(xiàn)方式??Java的虛擬機(jī)的
15、內(nèi)容。這部分主要包括三部分,GC、類加載機(jī)制,以及內(nèi)存。GC部分什么時(shí)候一個(gè)對(duì)象會(huì)被GC?1. 什么樣的對(duì)象是垃圾?一般來說,所有指向?qū)ο蟮囊枚家咽?,不可能再有程序能調(diào)用到這個(gè)對(duì)象,那么這個(gè)對(duì)象就成了垃圾,應(yīng)該被回收。1.1 根據(jù)這個(gè)思路,很容易就能想到用引用計(jì)數(shù)的辦法來確定一個(gè)對(duì)象是否是垃圾。即每當(dāng)多一個(gè)引用指向?qū)ο髸r(shí),引用計(jì)數(shù)加一,每當(dāng)少一個(gè)引用指向?qū)ο髸r(shí),引用計(jì)數(shù)減一,引用計(jì)數(shù)減到零,對(duì)象就可以被回收了。1.2 然而引用計(jì)數(shù)有一個(gè)致命問題不好解決,就是循環(huán)引用的問題。比如說一個(gè)循環(huán)鏈表,他們循環(huán)引用者,引用計(jì)數(shù)永遠(yuǎn)不會(huì)為零,但是實(shí)際上程序已經(jīng)不能訪問他們了,他們應(yīng)該被回收。1.3 所
16、以Java實(shí)際上是使用基于GC Roots的可達(dá)性分析,什么是GC Roots?所有類的靜態(tài)變量,每個(gè)線程調(diào)用棧上的本地變量。(實(shí)際上我們編程時(shí)也是要從這些地方開始訪問數(shù)據(jù)),所有這些對(duì)象,以及被這些對(duì)象所指向的對(duì)象,都是活的對(duì)象。活的對(duì)象所指向的對(duì)象也是活的對(duì)象。1.4 所以只要在GC的時(shí)刻,讓程序暫停運(yùn)行,然后從GC Roots開始分析,最后沒有被標(biāo)記為活對(duì)象的對(duì)象就是垃圾了。什么時(shí)候觸發(fā)GC1.當(dāng)應(yīng)用程序空閑時(shí),即沒有應(yīng)用線程在運(yùn)行時(shí),GC會(huì)被調(diào)用。因?yàn)镚C在優(yōu)先級(jí)最低的線程中進(jìn)行,所以當(dāng)應(yīng)用忙時(shí),GC線程就不會(huì)被調(diào)用,但以下條件除外。2.Java堆內(nèi)存不足時(shí),GC會(huì)被調(diào)用。當(dāng)應(yīng)用線程在
17、運(yùn)行,并在運(yùn)行過程中創(chuàng)建新對(duì)象,若這時(shí)內(nèi)存空間不足,JVM就會(huì)強(qiáng)制地調(diào)用GC線程,以便回收內(nèi)存用于新的分配。若GC一次之后仍不能滿足內(nèi)存分配的要求,JVM會(huì)再進(jìn)行兩次GC作進(jìn)一步的嘗試,若仍無法滿足要求,則 JVM將報(bào)“out of memory”的錯(cuò)誤,Java應(yīng)用將停止。GC算法標(biāo)記-清除算法 (Mark-Sweep)標(biāo)記-清除算法將垃圾回收分為兩個(gè)階段:標(biāo)記階段和清除階段。一種可行的實(shí)現(xiàn)是,在標(biāo)記階段首先通過根節(jié)點(diǎn),標(biāo)記所有從根節(jié)點(diǎn)開始的較大對(duì)象。因此,未被標(biāo)記的對(duì)象就是未被引用的垃圾對(duì)象。然后,在清除階段,清除所有未被標(biāo)記的對(duì)象。該算法最大的問題是存在大量的空間碎片,因?yàn)榛厥蘸蟮目臻g是
18、不連續(xù)的。在對(duì)象的堆空間分配過程中,尤其是大對(duì)象的內(nèi)存分配,不連續(xù)的內(nèi)存空間的工作效率要低于連續(xù)的空間。復(fù)制算法 (Copying)將現(xiàn)有的內(nèi)存空間分為兩快,每次只使用其中一塊,在垃圾回收時(shí)將正在使用的內(nèi)存中的存活對(duì)象復(fù)制到未被使用的內(nèi)存塊中,之后,清除正在使用的內(nèi)存塊中的所有對(duì)象,交換兩個(gè)內(nèi)存的角色,完成垃圾回收。如果系統(tǒng)中的垃圾對(duì)象很多,復(fù)制算法需要復(fù)制的存活對(duì)象數(shù)量并不會(huì)太大。因此在真正需要垃圾回收的時(shí)刻,復(fù)制算法的效率是很高的。又由于對(duì)象在垃圾回收過程中統(tǒng)一被復(fù)制到新的內(nèi)存空間中,因此,可確?;厥蘸蟮膬?nèi)存空間是沒有碎片的。該算法的缺點(diǎn)是將系統(tǒng)內(nèi)存折半。Java 的新生代串行垃圾回收器中
19、使用了復(fù)制算法的思想。新生代分為 eden 空間、from 空間、to 空間 3 個(gè)部分。其中 from 空間和 to 空間可以視為用于復(fù)制的兩塊大小相同、地位相等,且可進(jìn)行角色互換的空間塊。from 和 to 空間也稱為 survivor 空間,即幸存者空間,用于存放未被回收的對(duì)象。在垃圾回收時(shí),eden 空間中的存活對(duì)象會(huì)被復(fù)制到未使用的 survivor 空間中 (假設(shè)是 to),正在使用的 survivor 空間 (假設(shè)是 from) 中的年輕對(duì)象也會(huì)被復(fù)制到 to 空間中 (大對(duì)象,或者老年對(duì)象會(huì)直接進(jìn)入老年帶,如果 to 空間已滿,則對(duì)象也會(huì)直接進(jìn)入老年代)。此時(shí),eden 空間和
20、 from 空間中的剩余對(duì)象就是垃圾對(duì)象,可以直接清空,to 空間則存放此次回收后的存活對(duì)象。這種改進(jìn)的復(fù)制算法既保證了空間的連續(xù)性,又避免了大量的內(nèi)存空間浪費(fèi)。標(biāo)記-壓縮算法 (Mark-Compact)復(fù)制算法的高效性是建立在存活對(duì)象少、垃圾對(duì)象多的前提下的。這種情況在年輕代經(jīng)常發(fā)生,但是在老年代更常見的情況是大部分對(duì)象都是存活對(duì)象。如果依然使用復(fù)制算法,由于存活的對(duì)象較多,復(fù)制的成本也將很高。標(biāo)記-壓縮算法是一種老年代的回收算法,它在標(biāo)記-清除算法的基礎(chǔ)上做了一些優(yōu)化。也首先需要從根節(jié)點(diǎn)開始對(duì)所有可達(dá)對(duì)象做一次標(biāo)記,但之后,它并不簡單地清理未標(biāo)記的對(duì)象,而是將所有的存活對(duì)象壓縮到內(nèi)存的一
21、端。之后,清理邊界外所有的空間。這種方法既避免了碎片的產(chǎn)生,又不需要兩塊相同的內(nèi)存空間,因此,其性價(jià)比比較高。分代 (Generational Collecting)根據(jù)垃圾回收對(duì)象的特性,不同階段最優(yōu)的方式是使用合適的算法用于本階段的垃圾回收,分代算法即是基于這種思想,它將內(nèi)存區(qū)間根據(jù)對(duì)象的特點(diǎn)分成幾塊,根據(jù)每塊內(nèi)存區(qū)間的特點(diǎn),使用不同的回收算法,以提高垃圾回收的效率。以 Hot Spot 虛擬機(jī)為例,它將所有的新建對(duì)象都放入稱為年輕代的內(nèi)存區(qū)域,年輕代的特點(diǎn)是對(duì)象會(huì)很快回收,因此,在年輕代就選擇效率較高的復(fù)制算法。當(dāng)一個(gè)對(duì)象經(jīng)過幾次回收后依然存活,對(duì)象就會(huì)被放入稱為老生代的內(nèi)存空間。在老生
22、代中,幾乎所有的對(duì)象都是經(jīng)過幾次垃圾回收后依然得以幸存的。因此,可以認(rèn)為這些對(duì)象在一段時(shí)期內(nèi),甚至在應(yīng)用程序的整個(gè)生命周期中,將是常駐內(nèi)存的。如果依然使用復(fù)制算法回收老生代,將需要復(fù)制大量對(duì)象。再加上老生代的回收性價(jià)比也要低于新生代,因此這種做法也是不可取的。根據(jù)分代的思想,可以對(duì)老年代的回收使用與新生代不同的標(biāo)記-壓縮算法,以提高垃圾回收效率。GC策略Serial(串行GC)收集器Serial收集器是一個(gè)新生代收集器,單線程執(zhí)行,使用復(fù)制算法。它在進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程(用戶線程)。是Jvm client模式下默認(rèn)的新生代收集器。對(duì)于限定單個(gè)CPU的環(huán)境來說,Serial
23、收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率。ParNew(并行GC)收集器ParNew收集器其實(shí)就是serial收集器的多線程版本,除了使用多條線程進(jìn)行垃圾收集之外,其余行為與Serial收集器一樣。Parallel Scavenge(并行回收GC)收集器Parallel Scavenge收集器也是一個(gè)新生代收集器,它也是使用復(fù)制算法的收集器,又是并行多線程收集器。parallel Scavenge收集器的特點(diǎn)是它的關(guān)注點(diǎn)與其他收集器不同,CMS等收集器的關(guān)注點(diǎn)是盡可能地縮短垃圾收集時(shí)用戶線程的停頓時(shí)間,而parallel Scavenge收集器的目標(biāo)則是達(dá)到
24、一個(gè)可控制的吞吐量。吞吐量= 程序運(yùn)行時(shí)間/(程序運(yùn)行時(shí)間 + 垃圾收集時(shí)間),虛擬機(jī)總共運(yùn)行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。Serial Old(串行GC)收集器Serial Old是Serial收集器的老年代版本,它同樣使用一個(gè)單線程執(zhí)行收集,使用“標(biāo)記-整理”算法。主要使用在Client模式下的虛擬機(jī)。Parallel Old(并行GC)收集器Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標(biāo)記-整理”算法。CMS(并發(fā)GC)收集器CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間
25、為目標(biāo)的收集器。CMS收集器是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的,整個(gè)收集過程大致分為4個(gè)步驟:.初始標(biāo)記(CMS initial mark).并發(fā)標(biāo)記(CMS concurrenr mark).重新標(biāo)記(CMS remark).并發(fā)清除(CMS concurrent sweep) 其中初始標(biāo)記、重新標(biāo)記這兩個(gè)步驟任然需要停頓其他用戶線程。初始標(biāo)記僅僅只是標(biāo)記出GC ROOTS能直接關(guān)聯(lián)到的對(duì)象,速度很快,并發(fā)標(biāo)記階段是進(jìn)行GC ROOTS 根搜索算法階段,會(huì)判定對(duì)象是否存活。而重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間,因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,這個(gè)階段的停頓時(shí)間會(huì)被
26、初始標(biāo)記階段稍長,但比并發(fā)標(biāo)記階段要短。 由于整個(gè)過程中耗時(shí)最長的并發(fā)標(biāo)記和并發(fā)清除過程中,收集器線程都可以與用戶線程一起工作,所以整體來說,CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的。CMS收集器的優(yōu)點(diǎn):并發(fā)收集、低停頓,但是CMS還遠(yuǎn)遠(yuǎn)達(dá)不到完美,器主要有三個(gè)顯著缺點(diǎn):CMS收集器對(duì)CPU資源非常敏感。在并發(fā)階段,雖然不會(huì)導(dǎo)致用戶線程停頓,但是會(huì)占用CPU資源而導(dǎo)致引用程序變慢,總吞吐量下降。CMS默認(rèn)啟動(dòng)的回收線程數(shù)是:(CPU數(shù)量+3) / 4。CMS收集器無法處理浮動(dòng)垃圾,可能出現(xiàn)“Concurrent Mode Failure“,失敗后而導(dǎo)致另一次Full GC的產(chǎn)生。由
27、于CMS并發(fā)清理階段用戶線程還在運(yùn)行,伴隨程序的運(yùn)行自熱會(huì)有新的垃圾不斷產(chǎn)生,這一部分垃圾出現(xiàn)在標(biāo)記過程之后,CMS無法在本次收集中處理它們,只好留待下一次GC時(shí)將其清理掉。這一部分垃圾稱為“浮動(dòng)垃圾”。也是由于在垃圾收集階段用戶線程還需要運(yùn)行,即需要預(yù)留足夠的內(nèi)存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進(jìn)行收集,需要預(yù)留一部分內(nèi)存空間提供并發(fā)收集時(shí)的程序運(yùn)作使用。在默認(rèn)設(shè)置下,CMS收集器在老年代使用了68%的空間時(shí)就會(huì)被激活,也可以通過參數(shù)-XX:CMSInitiatingOccupancyFraction的值來提供觸發(fā)百分比,以降低內(nèi)存回收次數(shù)
28、提高性能。要是CMS運(yùn)行期間預(yù)留的內(nèi)存無法滿足程序其他線程需要,就會(huì)出現(xiàn)“Concurrent Mode Failure”失敗,這時(shí)候虛擬機(jī)將啟動(dòng)后備預(yù)案:臨時(shí)啟用Serial Old收集器來重新進(jìn)行老年代的垃圾收集,這樣停頓時(shí)間就很長了。所以說參數(shù)-XX:CMSInitiatingOccupancyFraction設(shè)置的過高將會(huì)很容易導(dǎo)致“Concurrent Mode Failure”失敗,性能反而降低。最后一個(gè)缺點(diǎn),CMS是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的收集器,使用“標(biāo)記-清除”算法收集后,會(huì)產(chǎn)生大量碎片。空間碎片太多時(shí),將會(huì)給對(duì)象分配帶來很多麻煩,比如說大對(duì)象,內(nèi)存空間找不到連續(xù)的空間來
29、分配不得不提前觸發(fā)一次Full GC。為了解決這個(gè)問題,CMS收集器提供了一個(gè)-XX:UseCMSCompactAtFullCollection開關(guān)參數(shù),用于在Full GC之后增加一個(gè)碎片整理過程,還可通過-XX:CMSFullGCBeforeCompaction參數(shù)設(shè)置執(zhí)行多少次不壓縮的Full GC之后,跟著來一次碎片整理過程。G1收集器G1(Garbage First)收集器是JDK1.7提供的一個(gè)新收集器,G1收集器基于“標(biāo)記-整理”算法實(shí)現(xiàn),也就是說不會(huì)產(chǎn)生內(nèi)存碎片。還有一個(gè)特點(diǎn)之前的收集器進(jìn)行收集的范圍都是整個(gè)新生代或老年代,而G1將整個(gè)Java堆(包括新生代,老年代)。類加載機(jī)
30、制Java的類加載器都有哪些?(1)啟動(dòng)類加載器(Bootstrap ClassLoader) 這個(gè)類加載器負(fù)責(zé)將存放在JAVA_HOME/lib下的,或者被-Xbootclasspath參數(shù)所指定的路徑中的,并且是虛擬機(jī)識(shí)別的類庫加載到虛擬機(jī)內(nèi)存中。啟動(dòng)類加載器無法被Java程序直接引用。(2)擴(kuò)展類加載器(Extension ClassLoader)這個(gè)加載器負(fù)責(zé)加載JAVA_HOME/lib/ext目錄中的,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫,開發(fā)者可以直接使用擴(kuò)展類加載器(3)應(yīng)用程序類加載器(Application ClassLoader)這個(gè)加載器是ClassLoader中g(shù)etSystemClassLoader()方法的返回值,所以一般也稱它為系統(tǒng)類加載器。它負(fù)責(zé)加載用戶類路徑(Classpath)上所指定的類庫,可直接使用這個(gè)加載器,如果應(yīng)用程序沒有自定義自己的類加載器,一般情況下這個(gè)就是程序中默認(rèn)的類加載器類加載之間的父子關(guān)系是怎樣的?Bootstrap沒有父加載器,Extension類加載器的父加載器為Bootstrap,Application類加載器的父加載器為Extension。什么是雙親委派模型雙親委派模型要求除了頂層的啟動(dòng)類加載器
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 小區(qū)物業(yè)裝修協(xié)議書
- 工程成品保護(hù)協(xié)議書
- 目標(biāo)估值協(xié)議書
- 宜賓航空服務(wù)協(xié)議書
- 短信合作協(xié)議書
- 家務(wù)分工離婚協(xié)議書
- 社科立項(xiàng)協(xié)議書
- 家庭托育合同協(xié)議書
- 百億送貸協(xié)議書
- 工程材料差價(jià)協(xié)議書
- 2025年高校教師資格證考試題庫(帶答案能力提升)
- 細(xì)胞培養(yǎng)技術(shù)考試試題資料
- 《小王子》講解+知識(shí)點(diǎn)+教案+課件
- 妊娠期糖尿病病人的護(hù)理查房
- 幼兒園大班游戲中“一對(duì)一傾聽”的策略
- 醫(yī)院信息安全管理課件
- 2024年初級(jí)會(huì)計(jì)實(shí)務(wù)考試真題
- 變電站設(shè)備危險(xiǎn)源辨識(shí)清單及預(yù)控措施
- GB/T 45083-2024再生資源分揀中心建設(shè)和管理規(guī)范
- 艾灸療法課件
- 銀行職業(yè)介紹課件
評(píng)論
0/150
提交評(píng)論