日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

推荐:Java性能优化系列集锦

發(fā)布時(shí)間:2024/1/17 java 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 推荐:Java性能优化系列集锦 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java性能問(wèn)題一直困擾著廣大程序員,由于平臺(tái)復(fù)雜性,要定位問(wèn)題,找出其根源確實(shí)很難。隨著10多年Java平臺(tái)的改進(jìn)以及新出現(xiàn)的多核多處理器,Java軟件的性能和擴(kuò)展性已經(jīng)今非昔比了?,F(xiàn)代JVM持續(xù)演進(jìn),內(nèi)建了更為成熟的優(yōu)化技術(shù)、運(yùn)行時(shí)技術(shù)和垃圾收集器。與此同時(shí),底層的硬件平臺(tái)和操作系統(tǒng)也在演化。

目錄:

一、Java性能優(yōu)化系列之一--設(shè)計(jì)優(yōu)化

二、Java性能優(yōu)化系列之二--程序優(yōu)化

三、Java性能優(yōu)化系列之三--并發(fā)程序設(shè)計(jì)詳解

四、Java性能優(yōu)化系列之四--Java內(nèi)存管理與垃圾回收機(jī)制詳解

五、Java性能優(yōu)化系列之五--JavaIO

現(xiàn)代大規(guī)模關(guān)鍵性系統(tǒng)中的Java性能調(diào)優(yōu),是一項(xiàng)富有挑戰(zhàn)的任務(wù)。你需要關(guān)注各種問(wèn)題,包括算法結(jié)構(gòu)、內(nèi)存分配模式以及磁盤和文件I/O的使用方式。性能調(diào)優(yōu)最困難的通常是找到問(wèn)題所在,即便是經(jīng)驗(yàn)豐富的人也會(huì)被他們的直覺(jué)所誤導(dǎo)。性能殺手總是隱藏在最意想不到的地方。

這一次,我將在本文中著重介紹Java性能優(yōu)化的一系列舉措,希望能夠?qū)ΜF(xiàn)在的你有所幫助。覺(jué)得有幫助的朋友也可以轉(zhuǎn)發(fā)、收藏一下。

?

一、Java性能優(yōu)化系列之一--設(shè)計(jì)優(yōu)化

1、善于利用 Java 中的設(shè)計(jì)模式:享元模式、代理模式、裝飾器模式等。詳見(jiàn)我的博客文章“大話”設(shè)計(jì)模式

文章鏈接:https://blog.csdn.net/person_limit/article/details/79806639

2、Java 中的緩沖區(qū):

(1)緩沖最常用的場(chǎng)景就是提高 IO 速度:比如 BufferedWriter 可以用來(lái)裝飾 FileWriter ,為 FileWriter 加上緩沖。 BufferedOutputStream 可以用來(lái)裝飾 FileOutputStream 。使用這兩個(gè)裝飾器時(shí)候可以指定緩沖區(qū)大小,默認(rèn)的 size 為 8K 。

(2)JavaNIO 中的各種 Buffer 類族,有更加強(qiáng)大的緩沖區(qū)控制功能。

(3)除了性能上的優(yōu)化,緩沖區(qū)也可以作為上層組件和下層組件的一種通信工具,將上層組件好下層組件進(jìn)行解耦。比如生產(chǎn)者消費(fèi)者模式中的緩沖區(qū)。

2、緩存:

(1)比如 Hibernate 采用的兩級(jí)緩存:一級(jí)緩存和二級(jí)緩存。二級(jí)緩存指的是 sessionFactory層面上的緩存, Hibernate 采用的是 EHCache 。一級(jí)緩存指的是 session 層面上的緩存。

3、對(duì)象復(fù)用技術(shù) -- 池的使用

(1)數(shù)據(jù)庫(kù)連接池:較常使用的數(shù)據(jù)庫(kù)連接池組件是 C3P0 和 Proxool 。其中 C3P0 是伴隨 Hibernate 一起發(fā)布的, Hibernate 默認(rèn)采用的數(shù)據(jù)庫(kù)連接池。

(2)線程池:自定義線程池以及 jdk1.5 提供的線程池組件。

4、并行代替串行。

5、時(shí)間換空間:不引入中間變量實(shí)現(xiàn)兩個(gè)數(shù)字的交換。代價(jià)是增加 CPU 運(yùn)算。

6、空間換時(shí)間:使用下標(biāo)數(shù)組排序。

?

二、Java性能優(yōu)化系列之二--程序優(yōu)化

常用的程序設(shè)計(jì)優(yōu)化技巧:

1、字符串優(yōu)化處理

(1)String 類的特點(diǎn):不變性、針對(duì)常量池的優(yōu)化( String.intern() 方法的意義)

(2)subString 方法的內(nèi)存泄漏 :

(3)字符串分割和查找不要使用 split 函數(shù),效率低,而是使用 StringTokenizer 或者 indexOf結(jié)合 subString() 函數(shù)完成分割。

(4)用 charAt ()方法代替 startWith ()方法。

(5)對(duì)于靜態(tài)字符串或者變量字符串的連接操作, Java 在編譯的時(shí)候會(huì)進(jìn)行徹底的優(yōu)化,將多個(gè)連接操作的字符串在編譯時(shí)合成一個(gè)單獨(dú)的字符串,而不是生成大量的 String 實(shí)例。只生成一個(gè)對(duì)象。

(6)在無(wú)需考慮線程安全情況下盡量使用 StringBuilder 。

(7)StringBuffer 和 StringBuilder 初始化的時(shí)候都可以設(shè)置一個(gè)初始值,默認(rèn)是 16B 。如果字符串的長(zhǎng)度大于 16B 的時(shí)候,則需要進(jìn)行擴(kuò)容。擴(kuò)容策略是將原有的容量大小翻倍,以新的容量申請(qǐng)內(nèi)存空間,建立 char 數(shù)組,然后將數(shù)組中的內(nèi)容復(fù)制到這個(gè)新的數(shù)組中,使用 Arrays.copyOf() 函數(shù)。因此,如果能預(yù)先評(píng)估 StringBuilder 的大小,則可以節(jié)省這些復(fù)制操作,從而提高系統(tǒng)的性能。

2、List 接口

( 1 ) ArrayList 和 Vector 的區(qū)別:它們幾乎使用了相同的算法,它們的唯一區(qū)別是對(duì)多線程的支持。 ArrayList 是不安全的,而 Vector 是線程安全的。

( 2 ) LinkedList 和 ArrayList 的區(qū)別:

|---1 、 linkedList 采用鏈表實(shí)現(xiàn),適合于數(shù)據(jù)刪除和插入非常頻繁的情況,不適合隨機(jī)訪問(wèn)。

|---2 、 ArrayList 采用數(shù)組實(shí)現(xiàn),適用于隨機(jī)查找和順序讀的情況,不適合刪除和插 入數(shù)據(jù)非常頻繁的場(chǎng)景。

(3)基于數(shù)組的 List 都會(huì)有一個(gè)容量參數(shù)。當(dāng) ArrayList 所存儲(chǔ)的元素容量超過(guò)其已有大小的時(shí)候就會(huì)進(jìn)行擴(kuò)容,數(shù)組的擴(kuò)容會(huì)導(dǎo)致整個(gè)數(shù)組進(jìn)行一次內(nèi)存復(fù)制。因此合理的數(shù)組大小會(huì)減小數(shù)組擴(kuò)容的次數(shù)從而提高系統(tǒng)性能。

(4)遍歷列表的時(shí)候盡量使用迭代器,速度塊。

2、Map 接口:

(1)HashMap 的實(shí)現(xiàn)原理:簡(jiǎn)單的說(shuō), HashMap 就是將 key 做 hash 算法,然后將 hash 值映射到內(nèi)存地址,直接取得 key 所對(duì)應(yīng)的數(shù)據(jù)。在 HashMap 中,底層數(shù)據(jù)結(jié)構(gòu)使用的是數(shù)組,所謂的內(nèi)存地址指的是數(shù)組的下標(biāo)索引。

(2)容量參數(shù)與擴(kuò)容:默認(rèn)情況下, hashmap 的初始容量為 16 ,負(fù)載因子為 0.75 ,也就是說(shuō)當(dāng) hashmap 的實(shí)際容量達(dá)到了初始容量 * 負(fù)載因子( hashmap 內(nèi)部維護(hù)的一個(gè) threshold 值)的時(shí)候, hashmap 就會(huì)進(jìn)行擴(kuò)容。在擴(kuò)容時(shí),會(huì)遍歷整個(gè) hashmap ,因此應(yīng)該設(shè)置合理的初始大小和負(fù)載因子,可以減小 hashmap 擴(kuò)容的次數(shù)。

(3)LinkedHashMap-- 有序的 HashMap : HashMap 的最大缺點(diǎn)是其無(wú)序性,被存入到 Hashmap 中的元素,在遍歷 HashMap 的時(shí)候,其輸出不一定按照輸入的順序,而是 HashMap 會(huì)根據(jù) hash 算法設(shè)定一個(gè)查找高效的順序。如果希望保存輸入順序,則需要使用 LinkedHashMap 。LinkedHashmap 在內(nèi)部又增加了一個(gè)鏈表,用于保存元素的順序。

(4)LinkedList 可以提供兩種類型的順序:一個(gè)是元素插入時(shí)候的順序,一個(gè)是最近訪問(wèn)的順序。注意: LinkedHashMap 在迭代過(guò)程中,如果設(shè)置為按照最后訪問(wèn)時(shí)間進(jìn)行排序,即:每當(dāng)使用 get() 方法訪問(wèn)某個(gè)元素時(shí),該元素便會(huì)移動(dòng)到鏈表的尾端。但是這個(gè)時(shí)候會(huì)出現(xiàn)異常,因此, LinkedHashMap 工作在這種模式的時(shí)候,不能在迭代器中使用 get() 操作。

(5)關(guān)于 ConcurrentModificationException :該異常一般會(huì)在集合迭代過(guò)程中被修改時(shí)拋出。因此,不要在迭代器模式中修改集合的結(jié)構(gòu)。這個(gè)特性適合于所有的集合類,包括 HashMap 、 Vector 、 ArrayList 等。

(6)TreeMap-- 如果要對(duì)元素進(jìn)行排序,則使用 TreeMap 對(duì) key 實(shí)現(xiàn)自定義排序,有兩種方式:在 TreeMap 的構(gòu)造函數(shù)中注入一個(gè) Comparator 或者使用一個(gè)實(shí)現(xiàn)了 Comparable 的 key 。

(7)如果需要將排序功能加入 HashMap ,最好是使用 Treemap 而不是在應(yīng)用程序自定義排序。

(8)HashMap 基于 Hash 表實(shí)現(xiàn), TreeMap 基于紅黑樹(shù)實(shí)現(xiàn)。

3 、 Map 和 Set 的關(guān)系:

( 1 )所有 Set 的實(shí)現(xiàn)都只是對(duì)應(yīng)的 Map 的一種封裝,其內(nèi)部維護(hù)一個(gè) Map 對(duì)象。即: Set只是相應(yīng)的 Map 的 Value 是一種特殊的表現(xiàn)形式的一種特例。

( 2 ) Set 主要有三種實(shí)現(xiàn)類: HashSet 、 LinkedHashSet 、 TreeSet 。其中 HashSet 是基于 Hash 的快速元素插入,元素之間無(wú)序。 LinkedHashSet 同時(shí)維護(hù)著元素插入順序,遍歷集合的時(shí)候,總是按照先進(jìn)先出的順序排序。 TreeSet 是基于紅黑樹(shù)的實(shí)現(xiàn),有著高效的基于元素 Key 的排序算法。

4 、優(yōu)化集合訪問(wèn)代碼:

( 1 )、分離循環(huán)中被重復(fù)調(diào)用的代碼:例如, for 循環(huán)中使用集合的 size() 函數(shù),則不應(yīng)該把這個(gè)函數(shù)的調(diào)用放到循環(huán)中,而是放到循環(huán)外邊、

( 2 )、省略相同的操作:

5 、 RandomAccess 接口:通過(guò) RandomAccess 可知道 List 是否支持隨機(jī)快速訪問(wèn)。同時(shí),如果應(yīng)用程序需要通過(guò)索引下標(biāo)對(duì) List 做隨機(jī)訪問(wèn),盡量 buyaoshiyongLinkedList , ArrayList 或者 Vector 可以。

6 、 JavaNIO 的特性:

1 、為所有的原始類型提供 Buffer 支持。

2 、使用 Java.nio.charset.Charset 作為字符編碼解碼解決方案。

3 、增加通道抽象代替原有的 IO 流抽象。

4 、支持鎖和內(nèi)存映射文件的文件訪問(wèn)接口。

5 、提供基于 Selector 的異步網(wǎng)絡(luò) IO 。

7 、 Java 中 NIO 的使用。 Channel 是一個(gè)雙向通道,即可讀也可寫。應(yīng)用程序不能直接操作 Channel ,必須借助于 Buffer 。例如讀數(shù)據(jù)的時(shí)候,必須把數(shù)據(jù)從通道讀入到緩沖區(qū),然后在緩沖區(qū)中進(jìn)行讀取。以文件讀取為例,首先通過(guò)文件輸入流獲得文件通道,然后把文件通道的內(nèi)容讀入到緩沖區(qū)中,然后就可以對(duì)緩沖區(qū)操作。

8 、 Buffer 的基本原理:

1 、 Buffer 的創(chuàng)建: Buffer 的靜態(tài) allocate(int size) 方法或者 Buffer.wrap(byte[]src) 。

2 、 Buffer 的工作原理:三個(gè)變量: position ,代表當(dāng)前緩沖區(qū)的位置,寫緩沖區(qū)的時(shí)候,將從 position 的下一個(gè)位置寫數(shù)據(jù)。 Capacity ,代表緩沖區(qū)的總?cè)萘可舷蕖?Limit ,緩沖區(qū)的實(shí)際上限,也就是說(shuō),讀數(shù)據(jù)的時(shí)候,數(shù)據(jù)即是從 position 到 limit 之間的數(shù)據(jù)

3 、 flip 操作: limit=position,position=0, 一般是在讀寫切換的時(shí)候使用。寫完數(shù)據(jù)之后,需要限定下有效數(shù)據(jù)范圍,才能讀數(shù)據(jù);

4 、 clear 操作: position-0 , limit=capacity. 。為重新寫入緩沖區(qū)做準(zhǔn)備。

5 、 rewind 操作: position=0 ,為讀取緩沖區(qū)中有效數(shù)據(jù)做準(zhǔn)備,一半 limit 已經(jīng)被合理設(shè)置。

9 、讀寫緩沖區(qū):

1 、 public byte get() :順序讀取緩沖區(qū)的一個(gè)字節(jié), position 會(huì)加一

2 、 public Buffer get(byte[]dst): 將緩沖區(qū)中的數(shù)據(jù)讀入到數(shù)組 dst 中,并適當(dāng)?shù)囊苿?dòng) position

3 、 public byte get(int index) :得到第 index 個(gè)字節(jié),但不移動(dòng) posoiion

4 、 public ByteBuffer put(byte b) :將字節(jié) b 放入到緩沖區(qū)中,并移動(dòng) position

5 、 public ByteBuffer put(int index,byte b) :將字節(jié) b 放到緩沖區(qū)的 index 位位置

6 、 pubglic final ByteBuffer(byte[]src) :將字節(jié)數(shù)組 src 放到緩沖區(qū)中。

10 、標(biāo)志緩沖區(qū):類似于一個(gè)書簽的功能,在數(shù)據(jù)的處理過(guò)程中,可隨時(shí)記錄當(dāng)前位置。然后在任意時(shí)刻,回到這個(gè)位置。 Mark 用于記錄當(dāng)前位置, reset 用于恢復(fù)到 mark 所在的位置、

11 、復(fù)制緩沖區(qū):使用 Buffer 的 duplicate 方法可以復(fù)制一個(gè)緩沖區(qū),副本緩沖區(qū)和原緩沖區(qū)共享一份空間但是有有著獨(dú)立的 position 、 capacity 和 limit 值。

20 、緩沖區(qū)分片:緩沖區(qū)分片使用 slice 方法實(shí)現(xiàn)。它將在現(xiàn)有的緩沖區(qū)中,創(chuàng)建的子緩沖區(qū)。子緩沖區(qū)和父緩沖區(qū)共享數(shù)據(jù)。這個(gè)方法有助于將系統(tǒng)模塊化。緩沖區(qū)切片可以將一個(gè)大緩沖區(qū)進(jìn)行分割處理,得到的子緩沖區(qū)都具有緩沖的緩沖區(qū)模型結(jié)構(gòu);因此。這個(gè)操作有助于系統(tǒng)的模塊化。

12 、只讀緩沖區(qū):只讀緩沖區(qū)可以保證核心數(shù)據(jù)的安全,如果不希望數(shù)據(jù)被隨意篡改,返回一個(gè)只讀緩沖區(qū)是很有幫助的。

13 、文件映射到內(nèi)存: NIO 提供了一種將文件映射到內(nèi)存的方法進(jìn)行 IO 操作,這種方法比基于流 IO 快很多。這個(gè)操作主要由 FileChanne.map() 操作。使用文件內(nèi)存的方式,將文本通過(guò) FileChannel 映射到內(nèi)存中。然后從內(nèi)存中讀取數(shù)據(jù)。同時(shí),通過(guò)修改 Buffer, 將對(duì)內(nèi)存中數(shù)據(jù)的修改寫到對(duì)應(yīng)的硬盤文件中。

14 、處理結(jié)構(gòu)化數(shù)據(jù):散射和聚集。散射就是將數(shù)據(jù)讀入到一組 bytebuffer 中,而聚集正好相反。通過(guò) ScatteringByteChannel 和 GatheringByteChannel 可以簡(jiǎn)化對(duì)結(jié)構(gòu)數(shù)據(jù)的操作。

15 、直接內(nèi)存訪問(wèn): DirectBuffer 直接分配在物理內(nèi)存中,并不占用對(duì)空間,因此也不受對(duì)空間限制。 DirectBuffer 的讀寫操作比普通 Buffer 塊,因?yàn)?DirectBuffer 直接操縱的就是內(nèi)核緩沖區(qū)。

16 、引用類型:強(qiáng)、軟、若、虛四種引用類型。

WeakHashMap :是弱引用的一中典型應(yīng)用,它使用弱引用作為內(nèi)部數(shù)據(jù)的存儲(chǔ)方案。可以作為簡(jiǎn)單的緩存表解決方案。

如果在系統(tǒng)中,需要一張很大的 Map 表, Map 中的表項(xiàng)作為緩存之用。這也意味著即使沒(méi)能從該 Map 中取得相應(yīng)地?cái)?shù)據(jù),系統(tǒng)也可以通過(guò)選項(xiàng)方案獲取這些數(shù)據(jù),雖然這樣會(huì)消耗更多的時(shí)間,但是不影響系統(tǒng)的正常運(yùn)行。這個(gè)時(shí)候,使用 WeakHashMap 是最合適的。因?yàn)?WeakHashMap 會(huì)在系統(tǒng)內(nèi)存范圍內(nèi),保存所有表項(xiàng),而一旦內(nèi)存不夠,在 GC 時(shí),沒(méi)有被引用的又會(huì)很快被清除掉,避免系統(tǒng)內(nèi)存溢出。

17 、有助于改善系統(tǒng)性能的技巧:

1 、慎用異常: for 循環(huán)中使用 try-catch 會(huì)大大降低系統(tǒng)性能

2 、使用局部變量:局部變量的訪問(wèn)速度遠(yuǎn)遠(yuǎn)高于類的靜態(tài)變量的訪問(wèn)速度,因?yàn)轭惖?變量是存在在堆空間中的。

3 、位運(yùn)算代替乘除法:右移代表除以二、左移代表乘以二。

4 、有的時(shí)候考慮是否可以使用數(shù)組代替位運(yùn)算。

5 、一維數(shù)組代替二維數(shù)組。

6 、提取表達(dá)式:盡可能讓程序少做重復(fù)的計(jì)算,尤其要關(guān)注在循環(huán)體的代碼,從循環(huán)提中提取重復(fù)的代碼可以有效的提升系統(tǒng)性能。

?

三、Java性能優(yōu)化系列之三--并發(fā)程序設(shè)計(jì)詳解

1、并發(fā)程序設(shè)計(jì)模式:

( 1 )、 Future-Callable 模式: FutureTask 類實(shí)現(xiàn)了 Runnable 接口,可以作為單獨(dú)的線程運(yùn)行,其 Run 方法中通過(guò) Sync 內(nèi)部類調(diào)用 Callable 接口,并維護(hù) Callable 接口的返回值。當(dāng)調(diào)用FutureTask.get() 的時(shí)候?qū)⒎祷?Callable 接口的返回對(duì)象。 Callable 接口是用戶自定義的實(shí)現(xiàn),通過(guò)實(shí)現(xiàn) Callable 接口的 call() 方法,指定 FutureTask 的實(shí)際工作內(nèi)容和返回對(duì)象。 Future 取得的結(jié)果類型和 Callable 返回的類型必須一致,這是由定義 FutureTask 的時(shí)候指定泛型保證的。 Callable 要采用 ExecutorSevice 的 submit 方法提交,返回的 future 對(duì)象可以取消任務(wù)。

( 2 )、 Master-Worker 格式:其核心思想是系統(tǒng)由兩類進(jìn)程協(xié)作工作: Master 進(jìn)程和 Worker 進(jìn)程。 Master 進(jìn)程負(fù)責(zé)接收和分配任務(wù), Worker 負(fù)責(zé)處理子任務(wù)。當(dāng)各個(gè)子任務(wù)處理完成后,將結(jié)果返回給 Master 進(jìn)程。由 Master 進(jìn)程進(jìn)行歸納會(huì)匯總,從而得到系統(tǒng)的最終結(jié)果。

( 3 )、保護(hù)暫停模式:其核心思想是僅當(dāng)服務(wù)進(jìn)程準(zhǔn)備好時(shí),才提供服務(wù)。設(shè)想一種場(chǎng)景,服務(wù)器會(huì)在很短時(shí)間內(nèi)承受大量的客戶端請(qǐng)求,客戶端請(qǐng)求的數(shù)量可能超過(guò)服務(wù)器本身的即時(shí)處理能力。為了不丟棄任意一個(gè)請(qǐng)求,最好的方式就是將這個(gè)客戶端進(jìn)行排列,由服務(wù)器逐個(gè)處理。

( 4 )、不變模式:為了盡可能的去除這些由于線程安全而引發(fā)的同步操作,提高并行程序性能 ,可以使用一種不可變的對(duì)象,依靠對(duì)象的不變性,可以確保在沒(méi)有同步操作的多線程環(huán)境中依然保持內(nèi)部狀態(tài)的一致性和正確性。

( 5 )、 Java 實(shí)現(xiàn)不變模式的條件:

1) 、去除 setter 方法以及所有修改自身屬性的方法。

2 )、將所有屬性設(shè)置為私有,并用 final 標(biāo)記,確保其不可修改。

3 )、確保沒(méi)有子類可以重載修改它的行為。

4 )、有一個(gè)可以創(chuàng)建完整對(duì)象的構(gòu)造函數(shù)。

Java 中,不變模式的使用有: java.lang.String 類。以及所有的元數(shù)據(jù)類包裝類。

(6)、生產(chǎn)者 - 消費(fèi)者模式:生產(chǎn)者進(jìn)程負(fù)責(zé)提交用戶請(qǐng)求,消費(fèi)者進(jìn)程負(fù)責(zé)具體處理生產(chǎn)者進(jìn)程提交的任務(wù)。生產(chǎn)者和消費(fèi)者之間通過(guò)共享內(nèi)存緩沖區(qū)進(jìn)行通信。通過(guò) Java 提供和餓 BlockingQueue 可以實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式。

2、JDK 多任務(wù)執(zhí)行框架:

( 1 )、簡(jiǎn)單線程池實(shí)現(xiàn):線程池的基本功能就是進(jìn)行線程的復(fù)用。當(dāng)系統(tǒng)接受一個(gè)提交的任務(wù),需要一個(gè)線程時(shí),并不著急立即去創(chuàng)建進(jìn)程,而是先去線程池查找是否有空余的進(jìn)程,若有則直接使用線程池中的線程工作。如果沒(méi)有,則再去創(chuàng)建新的進(jìn)程。待任務(wù)完成后,不是簡(jiǎn)單的銷毀進(jìn)程,而是將線程放入線程池的空閑隊(duì)列,等待下次使用。使用線程池之后,線程的創(chuàng)建和關(guān)閉通常由線程池維護(hù),線程通常不會(huì)因?yàn)闀?huì)執(zhí)行晚一次任務(wù)而被關(guān)閉,線程池中的線程會(huì)被多個(gè)任務(wù)重復(fù)使用。

( 2 )、 Executor 框架: Executor 框架提供了創(chuàng)建一個(gè)固定線程數(shù)量的線程池、返回一個(gè)只有一個(gè)線程的線程池、創(chuàng)建一個(gè)可根據(jù)實(shí)際情況進(jìn)行線程數(shù)量調(diào)整的線程池、可調(diào)度的單線程池以及可變線程數(shù)量的可調(diào)度的線程池。

( 3 )、自定義線程池 : 使用 ThreadPoolExecutor 接口: ThreadPoolExecutor 的構(gòu)造函數(shù)參數(shù)如下:

corePoolSize :指的是保留的線程池大小

maximumPoolSize : 指的是線程池的最大大小

keepAliveTime :指的是空閑線程結(jié)束的超時(shí)時(shí)間

Unit : 是一個(gè)枚舉,表示 keepAliveTime 的單位

workQueue : 表示存放任務(wù)的隊(duì)列。

ThreadFactory :創(chuàng)建線程的時(shí)候,使用到的線程工廠

handler : 當(dāng)線程達(dá)到最大限制,并且工作隊(duì)列里面也已近存放滿了任務(wù)的時(shí)候,決定如何處理提交到線程池的任務(wù)策略

上述的幾種線程池的內(nèi)部實(shí)現(xiàn)均使用了 ThreadPoolExecutor 接口。我們可以自定義提交但是未被執(zhí)行的任務(wù)隊(duì)列被執(zhí)行的順序,常見(jiàn)的有直接提交的隊(duì)列、有界的任務(wù)隊(duì)列、無(wú)界的任務(wù)隊(duì)列、優(yōu)先任務(wù)隊(duì)列,這樣可以在系統(tǒng)繁忙的時(shí)候忽略任務(wù)的提交先后次序,總是讓優(yōu)先級(jí)高的任務(wù)先執(zhí)行。使用優(yōu)先隊(duì)列時(shí),必須讓 target 實(shí)現(xiàn) Comparable 接口。

(4)、優(yōu)化線程池大小: NThreads=Ncpi*Ucpu*(1+W/C) , Java 中使用: Runtime.getRuntime().availableProcesses() 獲取可用的 CPU 數(shù)量。

3、JDK 并發(fā)數(shù)據(jù)結(jié)構(gòu):

( 1 )并發(fā) List : Vector 或者 CopyOnWriteArrayList 是兩個(gè)線程安全的 List 實(shí)現(xiàn)。

CopyOnWriteArrayList 很好的利用了對(duì)象的不變性,在沒(méi)有對(duì)對(duì)象進(jìn)行寫操作之前,由于對(duì)象未發(fā)生改變,因此不需要加鎖。而在試圖改變對(duì)象的時(shí)候,總是先獲得對(duì)象的一個(gè)副本,然后對(duì)副本進(jìn)行修改,最后將副本寫回。 CopyOnWriteArrayList 適合讀多寫少的高并發(fā)場(chǎng)合。而 Vector適合高并發(fā)寫的場(chǎng)合。

( 2 )并發(fā) Set : synchronizedSet 適合高并發(fā)寫的情景、 CopyOnWriteSet 適合讀多寫少的高并發(fā)場(chǎng)合。

( 3 )并發(fā) Map : ConcurrentHashMap 是專門為線程并發(fā)而設(shè)計(jì)的 HashMap ,它的 get 操作是無(wú)鎖的,其 put 操作的鎖粒度小于 SynchronizedHashMap ,因此其整體性能優(yōu)于 SynchronizedHashMap 。

( 4 )并發(fā) Queue :在并發(fā)隊(duì)列上, JDK 提供了兩種實(shí)現(xiàn),一個(gè)是以 ConcurrentLinkedQueue 為代表的高性能隊(duì)列,一個(gè)是以 BlockingQueue 接口為代表的阻塞隊(duì)列。如果需要一個(gè)能夠在高并發(fā)時(shí),仍能保持良好性能的隊(duì)列,可以使用 ConcurrentLinkedQueue 對(duì)象。而 BlockingQueue的主要適用場(chǎng)景就是生產(chǎn)者消費(fèi)者模式中的實(shí)現(xiàn)數(shù)據(jù)共享。 BlockingQueue 接口主要有兩種實(shí)現(xiàn): ArrayBlockingQueue 是一種基于數(shù)組的阻塞隊(duì)列實(shí)現(xiàn),也就是說(shuō)其內(nèi)部維護(hù)著一個(gè)定長(zhǎng)數(shù)組,用于緩存隊(duì)列中的數(shù)據(jù)對(duì)象。 LinkedBlockingQueue 則使用一個(gè)鏈表構(gòu)成的數(shù)據(jù)緩沖隊(duì)列。

4 、并發(fā)控制方法:

( 1 )、 Java 中的內(nèi)存模型與 Volatile :在 Java 中,每一個(gè)線程有一塊工作內(nèi)存區(qū),其中存放著被所有線程共享的主內(nèi)存中的變量的值的拷貝。當(dāng)線程執(zhí)行時(shí),它在自己的內(nèi)存中操作變量。為了存取一個(gè)共享的變量,一個(gè)線程通常要先獲取鎖定并且清除它的內(nèi)存緩沖區(qū),這保證該共享變量從所有線程的共享內(nèi)存區(qū)正確地裝入到線程的工作內(nèi)存區(qū);當(dāng)線程解鎖時(shí)保證該工作內(nèi)存區(qū)中變量的值寫回到共享內(nèi)存中。

( 2 )、 Volatile 關(guān)鍵字:聲明為 Volatile 的變量可以做以下保證:

1 )、其他線程對(duì)變量的修改,可以隨即反應(yīng)在當(dāng)前進(jìn)程中。

2 )、確保當(dāng)前線程對(duì) Volatile 變量的修改,能隨即寫回到共享主內(nèi)存中,并被其他線程所見(jiàn)

3 )、使用 Volatile 聲明的變量,編譯器會(huì)保證其有序性。

4 )、 double 和 long 類型的非原子處理:如果一個(gè) double 類型或者 long 類型的變量沒(méi)有被聲明為 volatile 類型,則變量在進(jìn)行 read 和 write 操作的時(shí)候,主內(nèi)存會(huì)把它當(dāng)成兩個(gè) 32 位的read 或者 write 操作。因此,在 32 為操作系統(tǒng)中,必須對(duì) double 或者 long 進(jìn)行同步

原因在于:使用 Volatile 標(biāo)志變量,將迫使所有線程均讀寫主內(nèi)存中的對(duì)應(yīng)變量,從而使得 Volatile 變量在多線程間可見(jiàn)。

(3)、同步關(guān)鍵字 -Synchronized ,其本質(zhì)是一把鎖: Synchronized 關(guān)鍵字可以作用在方法或者代碼塊中。當(dāng)作用的是成員方法時(shí),默認(rèn)的鎖是該對(duì)象 this ,這個(gè)時(shí)候一般在共享資源上進(jìn)行Synchronized 操作。該關(guān)鍵字一般和 wait ()和 notify ()方法一起使用,調(diào)用這兩個(gè)方法的時(shí)候一般指的是資源本身。由于所有的對(duì)象都能當(dāng)成資源,因此這兩個(gè)方法是從 Object 繼承而來(lái)的,而不是 Thread 或者 Runnable 才具有的方法。

(4)、 ReentrantLock 鎖:比 Synchronized 的功能更強(qiáng)大,可中斷、可定時(shí)。所有使用內(nèi)部鎖實(shí)現(xiàn)的功能,都可以使用重入鎖實(shí)現(xiàn)。重入鎖必須放入 finally 塊中進(jìn)行釋放,而內(nèi)部鎖可以自動(dòng)釋放。 重入鎖有著更強(qiáng)大的功能,比如提供了鎖等待時(shí)間 (boolean tryLock(long time.TimeUnit unit)) 、支持鎖中斷 (lockInterruptibly()) 和快速鎖輪詢 (boolean tryLock()) 以及一套 Condition 機(jī)制,這個(gè)機(jī)制類似于內(nèi)部鎖的 wait() 和 notify() 方法。

(5)、 ReadWriteLock :讀寫分列鎖。如果 系統(tǒng)中讀操作次數(shù)遠(yuǎn)遠(yuǎn)大于寫操作,而讀寫鎖就可以發(fā)揮巨大的作用。

(6)Condition 對(duì)象: await() 方法和 signal() 方法。 Condition 對(duì)象需要和重入鎖( ReentrantLock )配合工作以完成多線程協(xié)作的控制。

(7)Semaphore 信號(hào)量:信號(hào)量為多線程寫作提供了更為強(qiáng)大的控制方法。廣義上講,信號(hào)量是對(duì)鎖的擴(kuò)展。無(wú)論是內(nèi)部鎖( Synchronized )還是重入鎖( ReentrantLock ),一次都只允許一個(gè)進(jìn)程訪問(wèn)一個(gè)資源。而信號(hào)量卻可以指定多個(gè)線程同時(shí)訪問(wèn)某一個(gè)資源。

(8)ThreadLocal 線程局部變量: ThreadLocal 是一種多線程間并發(fā)訪問(wèn)變量的解決方案。與synchronized 等加鎖方式不同, ThreadLocal 完全不提供鎖,而使用以空間換時(shí)間的手段,為每個(gè)線程提供變量的獨(dú)立副本,以保障線程安全,因此并不是一種數(shù)據(jù)共享的解決方案。

5、同步工具類:

( 1 ) CountDownLatch (閉鎖):確保一個(gè)服務(wù)不會(huì)開(kāi)始,直到它依賴的其他服務(wù)都準(zhǔn)備就緒。 CountDownLatch 作用猶如倒計(jì)時(shí)計(jì)數(shù)器,調(diào)用 CountDownLatch 對(duì)象的 countDown 方法就將計(jì)數(shù)器減 1 ,當(dāng)計(jì)數(shù)到達(dá) 0 時(shí),則所有等待者或單個(gè)等待者開(kāi)始執(zhí)行。比如有 10 個(gè)運(yùn)動(dòng)員的田徑比賽 , ,有兩個(gè)裁判 A 和 B , A 在起點(diǎn)吹哨起跑, B 在終點(diǎn)記錄記錄并公布每個(gè)運(yùn)動(dòng)員的成績(jī)。剛開(kāi)始的時(shí)候,運(yùn)動(dòng)員們都趴在跑道上( A.await() )等到裁判吹哨。 A 吹哨耗費(fèi)了 5 秒,此時(shí)調(diào)用 A.countDown() 方法將等待時(shí)間減為 4 秒。當(dāng)減為 0 的時(shí)候,所有的運(yùn)動(dòng)員開(kāi)始起跑。這個(gè)時(shí)候, B 裁判開(kāi)始工作。啟動(dòng)一個(gè)初始值為 10 的定時(shí)器,每當(dāng)有一個(gè)運(yùn)動(dòng)員跑到重點(diǎn)的時(shí)候,就將計(jì)數(shù)器減一,代表已經(jīng)有一個(gè)運(yùn)動(dòng)員跑到終點(diǎn)。當(dāng)計(jì)時(shí)器為 0 的時(shí)候,代表所有的運(yùn)動(dòng)員都跑到了終點(diǎn)。此時(shí)可以根據(jù)公布成績(jī)了。

( 2 ) CylicBarrier (關(guān)卡):

1 )、類似于閉鎖,它們能夠阻塞一組線程直到某些事件發(fā)生

2 )、與同步鎖的不同之處是一個(gè)可以重用,一個(gè)不可以重用

3 )、所有線程必須同時(shí)到達(dá)關(guān)卡點(diǎn),才能繼續(xù)處理。

類似組團(tuán)旅游,導(dǎo)游就是一個(gè)關(guān)卡。表示大家彼此等待,大家集合好后才開(kāi)始出發(fā),分散活動(dòng)后又在指定地點(diǎn)集合碰面,這就好比整個(gè)公司的人員利用周末時(shí)間集體郊游一樣,先各自從家出發(fā)到公司集合后,再同時(shí)出發(fā)到公園游玩,在指定地點(diǎn)集合后再同時(shí)開(kāi)始就餐。

( 3 ) Exchanger :使用在兩個(gè)伙伴線程之間進(jìn)行數(shù)據(jù)交換,這個(gè)交換對(duì)于兩個(gè)線程來(lái)說(shuō)都是安全的。

講解 Exchanger 的比喻:好比兩個(gè)毒販要進(jìn)行交易,一手交錢、一手交貨,不管誰(shuí)先來(lái)到接頭地點(diǎn)后,就處于等待狀態(tài)了,當(dāng)另外一方也到達(dá)了接頭地點(diǎn)(所謂到達(dá)接頭地點(diǎn),也就是到到達(dá)了準(zhǔn)備接頭的狀態(tài))時(shí),兩者的數(shù)據(jù)就立即交換了,然后就又可以各忙各的了。

exchange 方法就相當(dāng)于兩手高高舉著待交換物,等待人家前來(lái)交換,一旦人家到來(lái)(即人家也執(zhí)行到 exchange 方法),則兩者立馬完成數(shù)據(jù)的交換。

5、關(guān)于死鎖:

(1)死鎖的四個(gè)條件:

1) 、互斥條件:一個(gè)資源只能被一個(gè)線程使用:

2 )、請(qǐng)求與保持條件:一個(gè)線程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得則資源保持不放。

3 )、不剝奪條件:進(jìn)程已經(jīng)獲得的資源,在未使用完之前,不能強(qiáng)行剝奪。

4 )、循環(huán)等待條件:若干個(gè)線程已經(jīng)形成了一種頭尾相接的循環(huán)等待資源關(guān)系。

(2)常見(jiàn)的死鎖:靜態(tài)順序死鎖、動(dòng)態(tài)順序死鎖、協(xié)作對(duì)象間的死鎖、線程饑餓死鎖。

(3)如何盡量避免死鎖:

1 )、制定鎖的順序,來(lái)避免死鎖

2 )、嘗試使用定時(shí)鎖( lock.tryLock(timeout) )

3 )、在持有鎖的方法中進(jìn)行其他方法的調(diào)用,盡量使用開(kāi)放調(diào)用(當(dāng)調(diào)用方法不需要持有鎖時(shí),叫做開(kāi)放調(diào)用)

4 )、減少鎖的持有時(shí)間、減小鎖代碼塊的粒度。

5 )、不要將功能互斥的 Task 放入到同一個(gè) Executor 中執(zhí)行。

6 、 代碼層面對(duì)鎖的優(yōu)化機(jī)制:

1 、避免死鎖

2 、減少鎖持有時(shí)間,代碼塊級(jí)別的鎖,而不是方法級(jí)別的鎖

3 、減小鎖粒度, ConcurrentHashMap 分段加鎖

4 、讀寫鎖代替獨(dú)占鎖

5 、鎖分離,例如 LinkedBlockingQueue 的尾插頭出的特點(diǎn),用兩把鎖 (putLock takeLock) 分離兩種操作。

6 、重入鎖和內(nèi)部鎖

重入鎖( ReentrantLock )和內(nèi)部鎖( Synchronized ):所有使用內(nèi)部鎖實(shí)現(xiàn)的功能,都可以使用重入鎖實(shí)現(xiàn)。重入鎖必須放入 finally 塊中進(jìn)行釋放,而內(nèi)部鎖可以自動(dòng)釋放。

重入鎖有著更強(qiáng)大的功能,比如提供了鎖等待時(shí)間 (boolean tryLock(long time.TimeUnit unit))、支持鎖中斷 (lockInterruptibly()) 和快速鎖輪詢 (boolean tryLock()) 以及一套 Condition 機(jī)制,這個(gè)機(jī)制類似于內(nèi)部鎖的 wait() 和 notify() 方法。想要獲取多線程面試題的可以加群:650385180,面試題及答案在群的共享區(qū)。

7 、鎖粗化:虛擬機(jī)在遇到一連串連續(xù)的對(duì)同一個(gè)鎖不斷進(jìn)行請(qǐng)求和釋放從操作的時(shí)候,便會(huì)把所有的鎖操作整合成對(duì)鎖的一次請(qǐng)求,從而減少對(duì)鎖的請(qǐng)求同步次數(shù)。

7 、 Java 虛擬機(jī)層面對(duì)鎖的優(yōu)化機(jī)制:

1、自旋鎖:由于線程切換(線程的掛起和恢復(fù))消耗的時(shí)間較大,則使線程在沒(méi)有獲得鎖時(shí),不被掛起,而轉(zhuǎn)而執(zhí)行一個(gè)空循環(huán)。在若干空循環(huán)后,線程如果獲得了鎖,而繼續(xù)執(zhí)行,若線程依然不能獲得鎖,而才被掛起。

2、鎖消除: JVM 通過(guò)對(duì)上下文的掃描,去除不可能存在共享資源競(jìng)爭(zhēng)的鎖,這樣可以節(jié)省毫無(wú)意義的請(qǐng)求鎖時(shí)間。比如單線程中或者非共享資源的常使用的 StringBuffer 和 Vector 。

3、鎖偏向:若某一個(gè)鎖被線程獲取后,便進(jìn)入偏向模式,當(dāng)線程再次請(qǐng)求這個(gè)鎖時(shí),無(wú)需進(jìn)行相關(guān)的同步操作,從而節(jié)省了操作時(shí)間。

8 、 Java 無(wú)鎖實(shí)現(xiàn)并發(fā)的機(jī)制:

( 1 )非阻塞的同步 / 無(wú)鎖: ThreadLocal ,讓每個(gè)進(jìn)程擁有各自獨(dú)立的變量副本,因此在并行計(jì)算時(shí)候,無(wú)須相互等待而造成阻塞。 CVS 算法的無(wú)鎖并發(fā)控制方法。

( 2 )原子操作: java.util.concurrent.atomic 包。

?

四、Java性能優(yōu)化系列之四--Java內(nèi)存管理與垃圾回收機(jī)制詳解

1 、 JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)域。

( 1 )、程序計(jì)數(shù)器:每一個(gè) Java 線程都有一個(gè)程序計(jì)數(shù)器來(lái)用于保存程序執(zhí)行到當(dāng)前方法的哪一個(gè)指令。此內(nèi)存區(qū)域是唯一一個(gè)在 JVM Spec 中沒(méi)有規(guī)定任何 OutOfMemoryError 情況的區(qū)域。

( 2 )、 Java 虛擬機(jī)棧:該塊內(nèi)存描述的是 Java 方法調(diào)用的內(nèi)存模型,每個(gè)方法在被執(zhí)行的時(shí)候,都會(huì)同時(shí)創(chuàng)建一個(gè)幀( Frame )用于存儲(chǔ)本地變量表、操作棧、動(dòng)態(tài)鏈接、方法出入口等信息。

( 3 )、本地方法棧。本地方法調(diào)用的內(nèi)存模型。

( 4 )、 Java 堆。 Java 中的對(duì)象以及類的靜態(tài)變量的存放地方。

( 5 )、方法區(qū):方法區(qū)中存放了每個(gè) Class 的結(jié)構(gòu)信息,包括常量池、字段描述、方法描述等等

( 6 )、運(yùn)行時(shí)常量池: Class 文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項(xiàng)信息是常量表 (constant_pool table) ,用于存放編譯期已可知的常量,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)(永久代)存放。但是 Java 語(yǔ)言并不要求常量一定只有編譯期預(yù)置入 Class 的常量表的內(nèi)容才能進(jìn)入方法區(qū)常量池,運(yùn)行期間也可將新內(nèi)容放入常量池(最典型的 String.intern() 方法)。運(yùn)行時(shí)常量池是方法區(qū)的一部分,自然受到方法區(qū)內(nèi)存的限制,當(dāng)常量池?zé)o法在申請(qǐng)到內(nèi)存時(shí)會(huì)拋出 OutOfMemoryError 異常。

( 7 )、本機(jī)直接內(nèi)存( Direct Memory )

在 JDK1.4 中新加入了 NIO 類,引入一種基于渠道與緩沖區(qū)的 I/O 方式,它可以通過(guò)本機(jī) Native 函數(shù)庫(kù)直接分配本機(jī)內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在 Java 堆里面的 DirectByteBuffer 對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣能在一些場(chǎng)景中顯著提高性能,因?yàn)楸苊饬嗽?Java 對(duì)和本機(jī)堆中來(lái)回復(fù)制數(shù)據(jù)。

2、Java 類加載機(jī)制的特點(diǎn):

(1)基于父類的委托機(jī)制:運(yùn)行一個(gè)程序時(shí),總是由 AppClass Loader (系統(tǒng)類加載器)開(kāi)始加載指定的類,在加載類時(shí),每個(gè)類加載器會(huì)將加載任務(wù)上交給其父,如果其父找不到,再由自己去加載, Bootstrap Loader (啟動(dòng)類加載器)是最頂級(jí)的類加載器了,其父加載器為 null 。如果父類加載器找不到給定的類名,則交由子加載器去加載,如果最低一層的子加載器也無(wú)法找到,則拋出異常。

(2)全盤負(fù)責(zé)機(jī)制:所謂全盤負(fù)責(zé),就是當(dāng)一個(gè)類加載器負(fù)責(zé)加載某個(gè) Class 時(shí),該 Class 鎖依賴的和引用的其他 Class 也將由該類加載器負(fù)責(zé)載入,除非顯式使用另外一個(gè)類加載器來(lái)載入。

(3)緩存機(jī)制:緩存機(jī)制將會(huì)保證所有加載過(guò)的 Class 對(duì)象都會(huì)被緩存,當(dāng)程序中需要使用某個(gè) Class 時(shí),類加載器會(huì)先從緩沖區(qū)中搜尋該 Class ,只有當(dāng)緩存區(qū)中不存在該 Class 對(duì)象時(shí),系統(tǒng)才會(huì)讀取該類對(duì)應(yīng)的二進(jìn)制數(shù)據(jù),并將其轉(zhuǎn)化為 Class 對(duì)象,存入緩存區(qū)中。這就是為什么修改了 Class 后,必須重新啟動(dòng) JVM ,程序所做的修改才會(huì)生效的原因。同時(shí),往們比較 A.getClass() 與 B.getClass() 是否相等時(shí),直接使用 == 比較,因?yàn)榫彺鏅C(jī)制保證類的字節(jié)碼在內(nèi)存中只可能存在一份。

(4)類加載器的三種方法以及其區(qū)別:

1)、命令行啟動(dòng)應(yīng)用時(shí)候由 JVM 初始化加載

2)、通過(guò) Class.forName() 方法動(dòng)態(tài)加載

3)、通過(guò) ClassLoader.loadClass() 方法動(dòng)態(tài)加載 // 使用 Class.forName() 來(lái)加載類,默認(rèn)會(huì)執(zhí)行初始化塊 , // 使用 Class.forName() 來(lái)加載類,并指定 ClassLoader ,初始化時(shí)不執(zhí)行靜態(tài)塊。

4)區(qū)別:使用 ClassLoader.loadClass() 來(lái)加載類,不會(huì)執(zhí)行初始化塊,

3 、類的主動(dòng)引用

什么情況下需要開(kāi)始類加載過(guò)程的第一個(gè)階段,也即類的初始化階段。 Java 虛擬機(jī)規(guī)定了有且只有 5 種情況下必須立即對(duì)類進(jìn)行初始化:

(1)、遇到 new 、 getstatic 、 putstatic 或 invokestatic 這四條字節(jié)碼指令時(shí),如果類沒(méi)有進(jìn)行過(guò)初始化,則需要觸發(fā)其初始化。(而且初始化的時(shí)候按照先父后子的順序)。這四條指令最常見(jiàn)的 Java 代碼場(chǎng)景是:使用 new 關(guān)鍵字實(shí)例化對(duì)象的時(shí)候、讀取或設(shè)置一個(gè)類的靜態(tài)字段(被 final 修飾,已在編譯時(shí)期把結(jié)果放入常量池的靜態(tài)字段除外)、調(diào)用一個(gè)類的靜態(tài)方法的的時(shí)候。

(2)使用 java.lang.reflect 包的方法對(duì)類進(jìn)行反射調(diào)用的時(shí)候,如果類沒(méi)有進(jìn)行過(guò)初始化,則需要先對(duì)其進(jìn)行初始化。

(3)當(dāng)初始化一個(gè)類的時(shí)候,如果發(fā)現(xiàn)其父類還沒(méi)有進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類的初始化。但是一個(gè)接口在初始化時(shí),并不要求其父類接口全部都完成了初始化,只有在真正使用到父接口的時(shí)候(如引用接口中定義的常量)才會(huì)被初始化。

(4)當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類(包含 main ()方法的那個(gè)類),虛擬機(jī)會(huì)先初始化這個(gè)主類。

(5)當(dāng)使用 jdk1.7 的動(dòng)態(tài)語(yǔ)言支持時(shí),如果一個(gè) java.lang.invoke.MethodHandle 實(shí)例最后的解析結(jié)果 REF_getStatic 、 REF_putStatic 、 REF_invokeStatic 的方法句柄,并且這個(gè)方法句柄所對(duì)應(yīng)的類沒(méi)有初始化過(guò),則需要先觸發(fā)其初始化。

4 、類的被動(dòng)引用

1、對(duì)于靜態(tài)字段,只有直接定義這個(gè)字段的類才會(huì)被初始化,因此通過(guò)其子類來(lái)引用父類中定義的靜態(tài)字段,只會(huì)觸發(fā)父類的初始化而不會(huì)觸發(fā)子類的初始化。

2、通過(guò)數(shù)組定義來(lái)引用類,不會(huì)觸發(fā)類的初始化 SuperClass[]sca=new SuperClass[10].

3、常量在編譯階段會(huì)存入調(diào)用類的常量池中,本質(zhì)上并沒(méi)有直接引用到定義常量的類,因此不會(huì)觸發(fā)常量的類的初始化。

5 、 Java 對(duì)象的創(chuàng)建過(guò)程以及如何保證對(duì)象創(chuàng)建的多線程的安全性:

虛擬機(jī)遇到一條 new 指令時(shí),首先將去檢查這個(gè)指令的參數(shù)是否能在常量池中定位到一個(gè)類的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類是否已經(jīng)被加載、解析和初始化過(guò)。如果沒(méi)有則進(jìn)行類加載過(guò)程。

在類加載通過(guò)后,接下來(lái)虛擬機(jī)將為新生對(duì)象分配內(nèi)存。對(duì)象所需的內(nèi)存的大小在類加載完成后便可完全確定。為對(duì)象分配空間的任務(wù)等價(jià)于把一塊確定大小的內(nèi)存從 Java 堆中劃分出來(lái)。

保證多線程的安全性。 有兩種方案,一種是對(duì)分配內(nèi)存的動(dòng)作進(jìn)行同步操作,實(shí)際上虛擬機(jī)采用 CAS 加上失敗重試的方式保證更新操作的原子性。另一種是把內(nèi)存分配的動(dòng)作按照線程劃分在不同的空間中進(jìn)行。即為每個(gè)線程在 Java 堆中預(yù)先分配一小塊內(nèi)存,成為本地線程分配緩沖( TLAB )。哪個(gè)線程要分配內(nèi)存,就在哪個(gè) TLAB 上分配,只有 TLAB 用完并分配新的 TLAB時(shí),才需要分配新的 TLAB 。

6、 什么時(shí)候判斷一個(gè)對(duì)象可以被回收?

用可達(dá)性分析算法。這個(gè)算法的基本思路就是通過(guò)一系列的成為“ GC roots ”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索,如果一個(gè)對(duì)象到 GCroots 沒(méi)有任何引用鏈相連,則證明此對(duì)象是不可用的??勺鳛?GCroots 的對(duì)象包括虛擬機(jī)棧中引用的對(duì)象、方法區(qū)中常量引用的對(duì)象、方法區(qū)中靜態(tài)屬性引用的對(duì)象或者本地方法棧中 JNI 引用的對(duì)象,這些對(duì)象的共同點(diǎn)都是生命周期與程序的生命周期一樣長(zhǎng),一般不會(huì)被 GC 。判斷一個(gè)對(duì)象死亡,至少經(jīng)歷兩次標(biāo)記過(guò)程:如果對(duì)象在進(jìn)行可達(dá)性算法后,發(fā)現(xiàn)沒(méi)有與 GC Roots 相連接的引用鏈,那他將會(huì)被第一次標(biāo)記,并在稍后執(zhí)行其 finalize ()方法。執(zhí)行是有機(jī)會(huì),并不一定執(zhí)行。稍后 GC 進(jìn)行第二次標(biāo)記,如果第一次標(biāo)記的對(duì)象在 finalize ()方法中拯救自己,比如把自己賦值到某個(gè)引用上,則第二次標(biāo)記時(shí)它將被移除出“即將回收”的集合,如果這個(gè)時(shí)候?qū)ο筮€沒(méi)有逃脫,那基本上就會(huì)被 GC 了。

7 、 關(guān)于 finalize ()方法的作用的說(shuō)明:

finalize ()方法的工作原理理論上是這樣的:一旦垃圾回收器準(zhǔn)備好釋放占用的存儲(chǔ)空間,將首先調(diào)用其 finalize ()方法,并且在下一次垃圾回收動(dòng)作發(fā)生時(shí),才會(huì)真正回收對(duì)象占用的內(nèi)存,所以使用 finalize ()的目的就是在垃圾回收時(shí)刻做一些重要的清理工作。我們知道,使用 GC 的唯一原因就是回收程序不再使用的內(nèi)存,所以對(duì)于與垃圾回收有關(guān)的任何行為來(lái)說(shuō),包括 finalize() 方法,它們也必須同內(nèi)存及其回收有關(guān)。個(gè)人認(rèn)為 Java 對(duì)象的 finalize ()方法有兩個(gè)作用( 1 )回收通過(guò)創(chuàng)建對(duì)象方式以外的方式為對(duì)象分配了存儲(chǔ)空間。比如,比如在 Java 代碼中采用了 JNI 操作,即在內(nèi)存分配時(shí),采用了類似 C 語(yǔ)言中的 malloc 函數(shù)來(lái)分配內(nèi)存,而且沒(méi)有調(diào)用free 函數(shù)進(jìn)行釋放。此時(shí)就需要在 finalize ()中用本地方法調(diào)用 free 函數(shù)以釋放內(nèi)存。( 2 )對(duì)象終結(jié)條件的驗(yàn)證,即用來(lái)判定對(duì)象是否符合被回收條件。比如,如果要回收一個(gè)對(duì)象,對(duì)象被清理時(shí)應(yīng)該處于某種狀態(tài),比如說(shuō)是一個(gè)打開(kāi)的文件,在回收之前應(yīng)該關(guān)閉這個(gè)文件。只要對(duì)象中存在沒(méi)有被適當(dāng)清理的部分, finalize ()就可以用來(lái)最終法相這種情況。因?yàn)閷?duì)象在被清理的時(shí)候肯定處于生命周期的最后一個(gè)階段,如果此時(shí)還含有一些未釋放的資源,則有能力釋放這些資源。這個(gè)不是 C/C++ 里面的析構(gòu)函數(shù),它運(yùn)行代價(jià)高昂,不確定性大,無(wú)法保證各個(gè)對(duì)象的調(diào)用順序。需要關(guān)閉外部資源之類的事情,基本上它能做的使用 try-finally 可以做的更好。

8 、 一個(gè)類被回收的條件。

(1)、該類所有的實(shí)例都已經(jīng)為 GC ,也就是說(shuō) JVM 中不存在該 Class 的任何實(shí)例。

(2)、加載該類的 ClassLoader 已經(jīng)被 GC 。

(3)該類對(duì)應(yīng)的 java.lang.Class 對(duì)象沒(méi)有在任何地方被引用,如不能在任何地方通過(guò)反射訪問(wèn)類的方法。

9、 垃圾回收算法 :

(1)、標(biāo)記 - 清除算法:標(biāo)記階段根據(jù)根節(jié)點(diǎn)標(biāo)記所有從根節(jié)點(diǎn)開(kāi)始的可達(dá)對(duì)象。則未被標(biāo)記的對(duì)象就是未被引用的垃圾對(duì)象,然后在清除階段,清楚所有未被標(biāo)記的對(duì)象。其最大缺點(diǎn)是空間碎片。

(2)、復(fù)制算法:將原有的內(nèi)存空間分為兩塊,每次只使用其中一塊,在垃圾回收時(shí),將正在使用的內(nèi)存中的存活對(duì)象復(fù)制到未使用的內(nèi)存塊中,之后清楚正在使用的內(nèi)存快中的所有對(duì)象,然后交換兩個(gè)內(nèi)存的角色。完成垃圾回收。這種算法比較適合新生代,因?yàn)樵谛律?#xff0c;垃圾對(duì)象通常會(huì)多于存活對(duì)象,復(fù)制算法效果較好。 Java 的新生代串行 GC 中,就使用了復(fù)制算法的思想。新生代分為 eden 空間、 from 空間和 to 空間三個(gè)部分。 From 和 to 空間可以視為用于復(fù)制的兩塊大小相同、地位相等、且可以進(jìn)行角色互換的空間塊。 From 和 to 空間也成為 survivor 空間,即幸存者空間,用于存放未被回收的對(duì)象。

(3)、標(biāo)記 - 壓縮算法:標(biāo)記過(guò)程與標(biāo)記清楚算法一樣,但后續(xù)不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象向一段移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。適合老年代的回收。

(4)、分代收集算法。

10 、 垃圾回收器。

( 1 )、 Serial 收集器

單線程收集器,收集時(shí)會(huì)暫停所有工作線程(我們將這件事情稱之為 Stop The World ,下稱 STW ),使用復(fù)制收集算法,虛擬機(jī)運(yùn)行在 Client 模式時(shí)的默認(rèn)新生代收集器。

(2)、 ParNew 收集器就是 Serial 的多線程版本,除了使用多條收集線程外,其余行為包括算法、 STW 、對(duì)象分配規(guī)則、回收策略等都與 Serial 收集器一摸一樣。對(duì)應(yīng)的這種收集器是虛擬機(jī)運(yùn)行在 Server 模式的默認(rèn)新生代收集器,在單 CPU 的環(huán)境中, ParNew 收集器并不會(huì)比 Serial 收集器有更好的效果。

(3)Parallel Scavenge 收集器(下稱 PS 收集器)也是一個(gè)多線程收集器,也是使用復(fù)制算法,但它的對(duì)象分配規(guī)則與回收策略都與 ParNew 收集器有所不同,它是以吞吐量最大化(即 GC 時(shí)間占總運(yùn)行時(shí)間最小)為目標(biāo)的收集器實(shí)現(xiàn),它允許較長(zhǎng)時(shí)間的 STW 換取總吞吐量最大化。

(4)4.Serial Old 收集器 Serial Old 是單線程收集器,使用標(biāo)記-整理算法,是老年代的收集器

(5) Parallel Old 收集器

老年代版本吞吐量?jī)?yōu)先收集器,使用多線程和標(biāo)記-整理算法, JVM 1.6 提供,在此之前,新生代使用了 PS 收集器的話,老年代除 Serial Old 外別無(wú)選擇,因?yàn)?PS 無(wú)法與 CMS 收集器配合工作。

(6)CMS ( Concurrent Mark Sweep )收集器

CMS 是一種以最短停頓時(shí)間為目標(biāo)的收集器,使用 CMS 并不能達(dá)到 GC 效率最高(總體 GC時(shí)間最小),但它能盡可能降低 GC 時(shí)服務(wù)的停頓時(shí)間,這一點(diǎn)對(duì)于實(shí)時(shí)或者高交互性應(yīng)用(譬如證券交易)來(lái)說(shuō)至關(guān)重要。

( 7 )、 G1 收集器。

11 、內(nèi)存分配與回收策略:

( 1 )、規(guī)則一:通常情況下,對(duì)象在 eden 中分配。當(dāng) eden 無(wú)法分配時(shí),觸發(fā)一次 Minor GC 。

( 2 )、規(guī)則二:配置了 PretenureSizeThreshold 的情況下,對(duì)象大于設(shè)置值將直接在老年代分配。

( 3 )、規(guī)則三:在 eden 經(jīng)過(guò) GC 后存活,并且 survivor 能容納的對(duì)象,將移動(dòng)到 survivor 空間內(nèi),如果對(duì)象在 survivor 中繼續(xù)熬過(guò)若干次回收(默認(rèn)為 15 次)將會(huì)被移動(dòng)到老年代中?;厥沾螖?shù)由 MaxTenuringThreshold 設(shè)置。

( 4 )、規(guī)則四:如果在 survivor 空間中相同年齡所有對(duì)象大小的累計(jì)值大于 survivor 空間的一半,大于或等于該年齡的對(duì)象就可以直接進(jìn)入老年代,無(wú)需達(dá)到 MaxTenuringThreshold 中要求的年齡。

( 5 )、規(guī)則五:在 Minor GC 觸發(fā)時(shí),會(huì)檢測(cè)之前每次晉升到老年代的平均大小是否大于老年代的剩余空間,如果大于,改為直接進(jìn)行一次 Full GC ,如果小于則查看 HandlePromotionFailure 設(shè)置看看是否允許擔(dān)保失敗,如果允許,那仍然進(jìn)行 Minor GC ,如果不允許,則也要改為進(jìn)行一次 Full GC 。

11、 關(guān)于 Minor GC 與 Full GC

Java 堆,分配對(duì)象實(shí)例所在空間,是 GC 的主要對(duì)象。分為新生代 (Young Generation/New)和老年代 (Tenured Generation/Old) 。新生代又劃分成 Eden Space 、 From Survivor/Survivor 0 、

To Survivor/Survivor 1 。

新生代要如此劃分是因?yàn)樾律褂玫?GC 算法是復(fù)制收集算法。新生代使用賦值收集算法,但是為了內(nèi)存利用率,只使用一個(gè) Survivor 空間來(lái)作為輪轉(zhuǎn)備份(之所以把該空間分為 FromSpace 和 ToSpace 兩部分是為了在 Minor GC 的時(shí)候把一些 age 大的對(duì)象從新生代空間中復(fù)制到老年代空間中)這種算法效率較高,而 GC 主要是發(fā)生在對(duì)象經(jīng)常消亡的新生代,因此新生代適合使用這種復(fù)制收集算法。由于有一個(gè)假設(shè):在一次新生代的 GC(Minor GC) 后大部分的對(duì)象占用的內(nèi)存都會(huì)被回收,因此留存的放置 GC 后仍然活的對(duì)象的空間就比較小了。這個(gè)留存的空間就是 Survivor space : From Survivor 或 To Survivor 。這兩個(gè) Survivor 空間是一樣大小的。例如,新生代大小是 10M(Xmn10M) ,那么缺省情況下 (-XX:SurvivorRatio=8) , Eden Space 是 8M , From 和 To 都是 1M 。

在 new 一個(gè)對(duì)象時(shí),先在 Eden Space 上分配,如果 Eden Space 空間不夠就要做一次 Minor GC 。 Minor GC 后,要把 Eden 和 From 中仍然活著的對(duì)象們復(fù)制到 To 空間中去。如果 To 空間不能容納 Minor GC 后活著的某個(gè)對(duì)象,那么該對(duì)象就被 promote 到老年代空間。從 Eden 空間被復(fù)制到 To 空間的對(duì)象就有了 age=1 。此 age=1 的對(duì)象如果在下一次的 Minor GC 后仍然存活,它還會(huì)被復(fù)制到另一個(gè) Survivor 空間 ( 如果認(rèn)為 From 和 To 是固定的,就是又從 To 回到了From 空間 ) ,而它的 age=2 。如此反復(fù),如果 age 大于某個(gè)閾值 (-XX:MaxTenuringThreshold=n),那個(gè)該對(duì)象就也可以 promote 到老年代了。

如果 Survivor 空間中相同 age( 例如, age=5) 對(duì)象的總和大于等于 Survivor 空間的一半,那么 age>=5 的對(duì)象在下一次 Minor GC 后就可以直接 promote 到老年代,而不用等到 age 增長(zhǎng)到閾值。

在做 Minor GC 時(shí),只對(duì)新生代做回收,不會(huì)回收老年代。即使老年代的對(duì)象無(wú)人索引也將仍然存活,直到下一次 Full GC 。

在發(fā)生 Minor GC 之前,虛擬機(jī)會(huì)先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對(duì)象總空間,如果這個(gè)條件成立,那么 Minor GC 可以確保是安全的。如果經(jīng)過(guò) Minor GC 后仍有大量對(duì)象存活的情況,則需要老年代進(jìn)行分配擔(dān)保,把 Survior 無(wú)法容納的對(duì)象直接進(jìn)入老年代。

13 、四種引用類型:

( 1 )、強(qiáng)引用:直接關(guān)聯(lián),虛擬機(jī)永遠(yuǎn)不會(huì)回收。

( 2 )、軟引用:描述一些還有用但并非必須的對(duì)象,虛擬機(jī)會(huì)在拋出內(nèi)存溢出異常之前會(huì)對(duì) 這些對(duì)象進(jìn)行第二次回收。

( 3 )弱引用:虛擬機(jī)一定會(huì)回收的對(duì)象

( 4 )虛引用:為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的就是能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。

14 、關(guān)于 Java 中生成對(duì)象的 4 種方式與區(qū)別:

( 1 )、使用 new 操作符,這是最普遍的一種(會(huì)調(diào)用相應(yīng)的構(gòu)造函數(shù)):

如: String s=new String("abc");

( 2 )使用反射動(dòng)態(tài)生成( 會(huì)調(diào)用相應(yīng)的構(gòu)造函數(shù) ):

利用 Class , ClassLoader , Constructor 中的方法可以動(dòng)態(tài)的生成類實(shí)例

如: Object o=Class.forName("java.lang.String").newInstance();

Object o=String.class.getClassLoader.loadClass("java.lang.String").newInstance();

以上的方式需要目標(biāo)類擁有公有無(wú)參構(gòu)造函數(shù)

以下使用 Constructor 進(jìn)行動(dòng)態(tài)生成

class User{

public User(String user,Integer id){}

}

Constructor c=User.class.getConstructor(new Class[]{String.class,Integer.class});

User user=(User)c.newInstance(new Object[]{"zhang san",123});

( 3 )使用克隆生成對(duì)象( 不會(huì)調(diào)用構(gòu)造函數(shù) )

例如使用一個(gè)實(shí)現(xiàn)了 Cloneable 接口的對(duì)象,調(diào)用其 clone() 方法獲得該對(duì)象的一份拷貝,使用 Java 序列化方式實(shí)現(xiàn)深拷貝。

( 4 )利用反序列化從流中生成對(duì)象( 不會(huì)調(diào)用構(gòu)造函數(shù) ):

利用 ObjectInptuStream 的 readObject() 方法生成對(duì)象

?

五、Java性能優(yōu)化系列之五--JavaIO

1 、關(guān)于 Java 序列化與反序列化:

(1)作用:

1、實(shí)現(xiàn)對(duì)象狀態(tài)的保存到本地,以便下一次啟動(dòng)虛擬機(jī)的時(shí)候直接讀取保存的序列化字節(jié)生成對(duì)象,而不是初始化對(duì)象; 2 、實(shí)現(xiàn)對(duì)象的網(wǎng)絡(luò)傳輸( RMI 分布對(duì)象); 3 、實(shí)現(xiàn)對(duì)象的深拷貝。

一:對(duì)象序列化可以實(shí)現(xiàn)分布式對(duì)象。主要應(yīng)用例如: RMI 要利用對(duì)象序列化運(yùn)行遠(yuǎn)程主機(jī)上的服務(wù),就像在本地機(jī)上運(yùn)行對(duì)象時(shí)一樣。

二: java 對(duì)象序列化不僅保留一個(gè)對(duì)象的數(shù)據(jù),而且遞歸保存對(duì)象引用的每個(gè)對(duì)象的數(shù)據(jù)??梢詫⒄麄€(gè)對(duì)象層次寫入字節(jié)流中,可以保存在文件中或在網(wǎng)絡(luò)連接上傳遞。利用對(duì)象序列化可以進(jìn)行對(duì)象的 " 深復(fù)制 " ,即復(fù)制對(duì)象本身及引用的對(duì)象本身。序列化一個(gè)對(duì)象可能得到整個(gè)對(duì)象序列。

(2)基本方式:

ObjectOutputStream 只能對(duì) Serializable 接口的類的對(duì)象進(jìn)行序列化。默認(rèn)情況下, ObjectOutputStream 按照默認(rèn)方式序列化,這種序列化方式僅僅對(duì)對(duì)象的非 transient 的實(shí)例變量進(jìn)行序列化,而不會(huì)序列化對(duì)象的 transient 的實(shí)例變量,也不會(huì)序列化靜態(tài)變量。

當(dāng) ObjectOutputStream 按照默認(rèn)方式反序列化時(shí),具有如下特點(diǎn):

1 ) 如果在內(nèi)存中對(duì)象所屬的類還沒(méi)有被加載,那么會(huì)先加載并初始化這個(gè)類。如果在 classpath 中不存在相應(yīng)的類文件,那么會(huì)拋出 ClassNotFoundException ;

2 ) 在反序列化時(shí)不會(huì)調(diào)用類的任何構(gòu)造方法。

如果用戶希望控制類的序列化方式,可以在可序列化類中提供以下形式的 writeObject() 和 readObject() 方法。

private void writeObject(java.io.ObjectOutputStream out) throws IOException

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

當(dāng) ObjectOutputStream 對(duì)一個(gè) Customer 對(duì)象進(jìn)行序列化時(shí),如果該對(duì)象具有 writeObject() 方法,那么就會(huì)執(zhí)行這一方法,否則就按默認(rèn)方式序列化。在該對(duì)象的 writeObjectt() 方法中,可以先調(diào)用 ObjectOutputStream 的 defaultWriteObject() 方法,使得對(duì)象輸出流先執(zhí)行默認(rèn)的序列化操作。同理可得出反序列化的情況,不過(guò)這次是 defaultReadObject() 方法。

有些對(duì)象中包含一些敏感信息,這些信息不宜對(duì)外公開(kāi)。如果按照默認(rèn)方式對(duì)它們序列化,那么它們的序列化數(shù)據(jù)在網(wǎng)絡(luò)上傳輸時(shí),可能會(huì)被不法份子竊取。對(duì)于這類信息,可以對(duì)它們進(jìn)行加密后再序列化,在反序列化時(shí)則需要解密,再恢復(fù)為原來(lái)的信息。

默認(rèn)的序列化方式會(huì)序列化整個(gè)對(duì)象圖,這需要遞歸遍歷對(duì)象圖。如果對(duì)象圖很復(fù)雜,遞歸遍歷操作需要消耗很多的空間和時(shí)間,它的內(nèi)部數(shù)據(jù)結(jié)構(gòu)為雙向列表。

在應(yīng)用時(shí),如果對(duì)某些成員變量都改為 transient 類型,將節(jié)省空間和時(shí)間,提高序列化的性能。

|-1 、實(shí)體對(duì)象實(shí)現(xiàn) seriable 接口以及自定義 seriousid 。

|-2 、 ObjectOutputStream out= new ObjectOutputStream(baos);

out.writeObject(new PersonDemo("rollen", 20));

out.close();

|-3 、 ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());

ObjectInputStream input=new ObjectInputStream(bais);

Object obj =input.readObject();

input.close();

(3)Java 自定義序列化反序列化:復(fù)寫實(shí)現(xiàn)了 seriliable 的實(shí)體類的 readObject() 和 writeObject() 的方法的原因:

有些對(duì)象中包含一些敏感信息,這些信息不宜對(duì)外公開(kāi)。如果按照默認(rèn)方式對(duì)它們序列化,那么它們的序列化數(shù)據(jù)在網(wǎng)絡(luò)上傳輸時(shí),可能會(huì)被不法份子竊取。對(duì)于這類信息,可以對(duì)它們進(jìn)行加密后再序列化,在反序列化時(shí)則需要解密,再恢復(fù)為原來(lái)的信息。此時(shí)便不能使用默認(rèn)的 readObject 和 writeObject() 方法。

private void writeObject(java.io.ObjectOutputStream out) throws IOException{

out.defaultWriteObject();

out.writeUTF(name);

}

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{

in.defaultReadObject();

name=in.readUTF();

}

一般情況直接實(shí)現(xiàn) Serializable 接口就可以實(shí)現(xiàn)序列化的要求,但是有些情況需要對(duì)序列化做一些特殊的要求。

(4)Transits 關(guān)鍵字的作用:屏蔽一些不想進(jìn)行序列化的成員變量,解屏蔽的方法可以用( 3)

(5)Externalize 的作用:

Externalizable 接口繼承自 Serializable 接口,如果一個(gè)類實(shí)現(xiàn)了 Externalizable 接口,那么將完全由這個(gè)類控制自身的序列化行為。 Externalizable 接口聲明了兩個(gè)方法:

public void writeExternal(ObjectOutput out) throws IOException

public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException

前者負(fù)責(zé)序列化操作,后者負(fù)責(zé)反序列化操作。

在對(duì)實(shí)現(xiàn)了 Externalizable 接口的類的對(duì)象進(jìn)行反序列化時(shí), 會(huì)先調(diào)用類的不帶參數(shù)的構(gòu)造方法,這是有別于默認(rèn)反序列方式的。如果把類的不帶參數(shù)的構(gòu)造方法刪除 ,或者把該構(gòu)造方法的訪問(wèn)權(quán)限設(shè)置為 private 、默認(rèn)或 protected 級(jí)別,會(huì)拋出 java.io.InvalidException: no valid constructor 異常。

(6)與 Java 構(gòu)造函數(shù)的關(guān)系:

實(shí)現(xiàn)了 Externalizable 接口的類的對(duì)象進(jìn)行反序列化時(shí),會(huì)先調(diào)用類的不帶參數(shù)的構(gòu)造方法;而實(shí)現(xiàn)了 Serializable 接口的類的對(duì)象進(jìn)行反序列化時(shí),不會(huì)調(diào)用任何構(gòu)造方法。僅僅是根據(jù)所保存的對(duì)象的狀態(tài)信息,在內(nèi)存中重新構(gòu)建對(duì)象!

(7)注意事項(xiàng):

1) 、序列化運(yùn)行時(shí)使用一個(gè)稱為 serialVersionUID 的版本號(hào)與每個(gè)可序列化類相關(guān)聯(lián),該序列號(hào)在反序列化過(guò)程中用于驗(yàn)證序列化對(duì)象的發(fā)送者和接收者是否為該對(duì)象加載了與序列化兼容的類。為它賦予明確的值。顯式地定義 serialVersionUID 有兩種用途:

在某些場(chǎng)合,希望類的不同版本對(duì)序列化兼容,因此需要確保類的不同版本具有相同的 serialVersionUID ;

在某些場(chǎng)合,不希望類的不同版本對(duì)序列化兼容,因此需要確保類的不同版本具有不同的 serialVersionUID 。

2)、 java 有很多基礎(chǔ)類已經(jīng)實(shí)現(xiàn)了 serializable 接口,比如 string,vector 等。但是比如 hashtable 就沒(méi)有實(shí)現(xiàn) serializable 接口。

3)、并不是所有的對(duì)象都可以被序列化。由于安全方面的原因一個(gè)對(duì)象擁有 private,public 等 field, 對(duì)于一個(gè)要傳輸?shù)膶?duì)象 , 比如寫到文件 , 或者進(jìn)行 rmi 傳輸?shù)鹊?, 在序列化進(jìn)行傳輸?shù)倪^(guò)程中 ,這個(gè)對(duì)象的 private 等域是不受保護(hù)的;資源分配方面的原因 , 比如 socket,thread 類 , 如果可以序列化 , 進(jìn)行傳輸或者保存 , 也無(wú)法對(duì)他們進(jìn)行重新的資源分配 , 而且 , 也是沒(méi)有必要這樣實(shí)現(xiàn) .

4)、反序列化對(duì)象時(shí),并不會(huì)調(diào)用該對(duì)象的任何構(gòu)造方法,僅僅是根據(jù)所保存的對(duì)象的狀態(tài)信息,在內(nèi)存中重新構(gòu)建對(duì)象!

5)、當(dāng)一個(gè)對(duì)象被序列化時(shí),只保存對(duì)象的非靜態(tài)成員變量,不能保存任何的成員方法和靜態(tài)的成員變量

6)、如果一個(gè)對(duì)象的成員變量是一個(gè)對(duì)象,那么這個(gè)對(duì)象的數(shù)據(jù)成員也會(huì)被保存!這是能用序列化解決深拷貝的重要原因。

(8)序列化與單例模式的沖突解決辦法:

另外還有兩個(gè)自定義序列化方法 writeReplace 和 readResolve ,分別用來(lái)在序列化之前替換序列化對(duì)象 和 在反序列化之后的對(duì)返回對(duì)象的處理。一般可以用來(lái)避免 singleTon 對(duì)象跨 jvm 序列化和反序列化時(shí)產(chǎn)生多個(gè)對(duì)象實(shí)例,事實(shí)上 singleTon 的對(duì)象一旦可序列化,它就不能保證 singleTon 了。 JVM 的 Enum 實(shí)現(xiàn)里就是重寫了 readResolve 方法,由 JVM 保證 Enum 的值都是 singleTon 的,所以建議多使用 Enum 代替使用 writeReplace 和 readResolve 方法。

Java 代碼

private Object readResolve()

{

return INSTANCE;

}

private Object writeReplace(){

return INSTANCE;

}

注: writeReplace 調(diào)用在 writeObject 前 ;readResolve 調(diào)用在 readObject 之后。

(9)序列化解決深拷貝的代碼:

public Object deepClone() throws IOException, OptionalDataException,

ClassNotFoundException {

// 將對(duì)象寫到流里

ByteArrayOutputStream bo = new ByteArrayOutputStream();

ObjectOutputStream oo = new ObjectOutputStream(bo);

oo.writeObject(this); // 從流里讀出來(lái)

ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());

ObjectInputStream oi = new ObjectInputStream(bi);

return (oi.readObject());

}

對(duì)象所屬的類要實(shí)現(xiàn) Serializable 接口。同時(shí)將該方法寫入到對(duì)象所屬的類中。

深拷貝的時(shí)候,調(diào)用該方法即可。

2、JavaIO 中的裝飾模式:

Java 中使用的最廣泛的裝飾器模式就是 JavaIO 類的設(shè)計(jì)。比如, OutPutStream 是輸出流的基類,其子類有 FileOutputStream 和 FilterOutputStream, 而 FilterOutputStream 的子類有 BufferedOutputStream 和 DataOutputStream 兩個(gè)子類。其中, FileOutputStream 為系統(tǒng)的核心類,它實(shí)現(xiàn)了向文件寫數(shù)據(jù)的功能,使用 DataOutputStream 可以在 FileOutputStream 的基礎(chǔ)上增加多種數(shù)據(jù)類型的寫操作支持( DataOutputStream 類中有 writeUTF 、 writeInt 等函數(shù)),而 BufferdOutputStream 裝飾器可以對(duì) FileOutputStream 增加緩沖功能,優(yōu)化 I/O 性能。

3、JavaIO 流的使用場(chǎng)景:

(1)IO 流:用于處理設(shè)備上的數(shù)據(jù),這里的設(shè)備指的是:硬盤上的文件、內(nèi)存、鍵盤輸入、屏幕顯示。

(2)字節(jié)流和字符流:字節(jié)流好理解,因?yàn)樗懈袷降奈募际且宰止?jié)形式硬盤上存儲(chǔ)的,包括圖片、 MP3 、 avi 等,因此字節(jié)流可以處理所有類型的數(shù)據(jù)。字符流讀取的時(shí)候讀到一個(gè)或多個(gè)字節(jié)時(shí)(中文對(duì)應(yīng)的 字節(jié)數(shù)是兩個(gè),在 UTF-8 碼表中是三個(gè)字節(jié))時(shí),先去查指定的編碼表,將查到的字符返回。字符流之所以出現(xiàn),就是因?yàn)橛辛宋募幋a的不同,而有了對(duì)字符進(jìn)行高效操作的字符流對(duì)象。因此,只要是處理純文本數(shù)據(jù),就要優(yōu)先考慮使用字符流,除此之外都使用字節(jié)流。

(3)流操作的基本規(guī)律:

1 )、明確數(shù)據(jù)源和數(shù)據(jù)匯,目的是明確使用輸入流還是輸出流。

2 )、明確操作的數(shù)據(jù)是否是純文本數(shù)據(jù)。

3 )、是否需要進(jìn)行字節(jié)流和字符流的轉(zhuǎn)換。

4 )、是否需要使用緩存。

(4)實(shí)例說(shuō)明流操作的基本流程:把鍵盤上讀入的數(shù)據(jù)以指定的編碼存入到文件中。

1 )、明白數(shù)據(jù)源:鍵盤輸入, System.in ,可用 InputStream 和 Reader

2 )、發(fā)現(xiàn) System.in 對(duì)應(yīng)的流是字節(jié)讀入流,所以要將其進(jìn)行轉(zhuǎn)換,將字節(jié)轉(zhuǎn)換為字符。

3 )、所以要使用 InputStreamReader 轉(zhuǎn)換流

4 )、如果想提高效率,要加入緩存機(jī)制,那么就要加入字符流的緩沖區(qū)。 BufferedReader,因此前四步構(gòu)造出的輸入流為:

BufferedReader bur = new BufferedReader(new InputStreamReader(System.in));

5 )、明白數(shù)據(jù)匯:既然是數(shù)據(jù)匯,則一定是輸出流,可以用 OutputStream 或 Writer 。

6 )、往文件中存儲(chǔ)的都是文本文件,因此選用 Writer 。

7 )、因?yàn)橐付ň幋a表,所以使用 Writer 中的轉(zhuǎn)換流, OutputStreamWriter 。

注意:雖然最終是文件,但是不可以選擇 FileWriter ,因?yàn)樵搶?duì)象是使用默認(rèn)編碼表。

8 )是否要提高效率,選擇 BufferedWriter 。

9 )轉(zhuǎn)換輸出流需要接收一個(gè)字節(jié)輸出流進(jìn)來(lái),所以要是用 OutputStream 體系,而最終輸出到一個(gè)文件中。那么就要使用 OutputStream 體系中可以操作的文件的字符流對(duì)象, FileOutputStream 。

10 )、通過(guò)前面的分析,得到的輸出流對(duì)象如下:

//String charSet = System.getProperty("file.encoding");

String charSet = "utf-8";

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new

FileOutputStream("a.txt"),charSet);

4 、可以和流相關(guān)聯(lián)的集合對(duì)象 Properties 。

Map

|--HashTable

|--Properties

Properties :該集合不需要泛型,因?yàn)樵摷现械逆I值都是 String 類型。

5、其他流對(duì)象:

( 1 )打印流:

PrintStream :是一個(gè)字節(jié)打印流 System.out 對(duì)應(yīng)的就是 PrintStream 。它的構(gòu)造函數(shù)可以接收三種數(shù)據(jù)類型的值:字符串路徑、 File 對(duì)象、 OutputStream (當(dāng)為 System.out 的時(shí)候即把輸入顯示到屏幕上)

PrintWriter :是一個(gè)字符打印流。構(gòu)造函數(shù)可以接收四種類型的值。字符串路徑、 File 對(duì)象(對(duì)于這兩中類型的數(shù)據(jù),還可以指定編碼表。也即是是字符集)、 OutPutSream 、 Writer (對(duì)于三、四類型的數(shù)據(jù),可以指定自動(dòng)刷新,注意:當(dāng)自動(dòng)刷新的值為 true 時(shí),只有三個(gè)方法可以用: printlf 、 printf 、 format )

(2)管道流: PipedOutputStream 和 PipedInputStream 。一般在多線程中通信的時(shí)候用。

(3)RandomAccessFile :該對(duì)象不是流體系中的一員,但是該隊(duì)選中封裝了字節(jié)流,同時(shí)還封裝了一個(gè)緩沖區(qū)(字節(jié)數(shù)組),通過(guò)內(nèi)部的指針來(lái)操作數(shù)組中的數(shù)據(jù)。該對(duì)象特點(diǎn):只能操作文件和對(duì)文件讀寫都可以。多用于多線程下載。、

(4)合并流:可以將多個(gè)讀取流合并成一個(gè)流。其實(shí)就是將每一個(gè)讀取流對(duì)象存儲(chǔ)到一個(gè)集合中,最后一個(gè)流對(duì)象結(jié)尾作為這個(gè)流的結(jié)尾。

(5)對(duì)象的序列化。 ObjectInputStream 和 ObjectInputStream 。

(6)操作基本數(shù)據(jù)類型的流對(duì)象: DataInputStream 和 DataOutputStream 。

(7)操縱內(nèi)存數(shù)組的流對(duì)象,這些對(duì)象的數(shù)據(jù)源是內(nèi)存,數(shù)據(jù)匯也是內(nèi)存: ByteArrayInputStream 和 ByteArrayOutputStream , CharArrayReader 和 CharArrayWriter 。這些流并未調(diào)用系統(tǒng)資源,使用的是內(nèi)存中的數(shù)組,所以在使用的時(shí)候不用 close 。

(8)編碼轉(zhuǎn)換:

在 IO 中涉及到編碼轉(zhuǎn)換的流是轉(zhuǎn)換流和打印流,但是打印流只有輸出。轉(zhuǎn)換流是可以指定編碼表的,默認(rèn)情況下,都是本機(jī)默認(rèn)的編碼表, GBK ??梢酝ㄟ^(guò): Syetem.getProperty( “file.encoding”) 得到。字符串到字節(jié)數(shù)組成為編碼的過(guò)程,通過(guò) getBytes(charset) 完成,從字節(jié)數(shù)組到字符串的過(guò)程是解碼的過(guò)程,通過(guò) String 類的構(gòu)造函數(shù)完成 String ( byte[],charset ) .

(9)編碼實(shí)例與解析:

(10)JavaNIO 的 Charset 類專門用來(lái)編碼和解碼。

想要了解更多分布式知識(shí)點(diǎn)的,可以關(guān)注我一下,我后續(xù)也會(huì)整理更多關(guān)于分布式架構(gòu)這一塊的知識(shí)點(diǎn)分享出來(lái),另外順便給大家推薦一個(gè)交流學(xué)習(xí)群:650385180,里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源,目前受益良多,以下的課程體系圖也是在群里獲取。

轉(zhuǎn)載于:https://www.cnblogs.com/lfs2640666960/p/8718064.html

總結(jié)

以上是生活随笔為你收集整理的推荐:Java性能优化系列集锦的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

天堂网一区二区 | 国产精品免费观看久久 | 黄色资源在线观看 | 91污视频在线观看 | av高清在线 | 久久伊人综合 | 久久久久国产精品一区 | 一区二区欧美激情 | 国产精品成人一区二区三区吃奶 | av中文字幕在线电影 | 日本成人中文字幕在线观看 | 97超级碰碰 | 色吊丝在线永久观看最新版本 | 日韩精品一区二区三区三炮视频 | 日韩在线观看视频网站 | 欧美一区二区三区在线播放 | 国产中文欧美日韩在线 | 色天天久久 | 99国产一区 | 免费看国产精品 | 91久久偷偷做嫩草影院 | 色视频网站在线 | 国产美女精品视频免费观看 | 在线观看成人av | 国产精品免费av | 免费看精品久久片 | 国内小视频 | 国产成人l区 | 精品一区二区免费在线观看 | 一级黄色片在线免费观看 | 91精品婷婷国产综合久久蝌蚪 | 国内精品久久久久国产 | 国产精品激情 | 最近免费观看的电影完整版 | 美女黄频在线观看 | 中文字幕中文字幕在线中文字幕三区 | 国产精品久久久区三区天天噜 | 国产精品永久免费 | 欧美一性一交一乱 | 国产手机视频在线观看 | 日韩精品一区二区三区在线视频 | 在线观看中文字幕一区二区 | 国内外成人在线 | 亚洲国产欧美一区二区三区丁香婷 | 国产高清黄色 | 少妇bbb搡bbbb搡bbbb′ | 免费一级黄色 | 一个色综合网站 | 国产不卡在线看 | 丁香av在线| 久草免费在线视频观看 | 日日干干夜夜 | 久久久九色精品国产一区二区三区 | 日韩在线视频网址 | 国产一区二区高清 | 九九久久婷婷 | 成全在线视频免费观看 | 免费在线黄网 | 成人免费共享视频 | 中文字幕第一页在线 | www.色婷婷.com| 欧美性护士 | 天天射狠狠干 | 久久精品爱爱视频 | 成人97视频 | 激情视频一区二区三区 | 午夜电影久久 | 精品国产乱码一区二区三区在线 | 色吧久久 | 一级成人网 | 国产精品无 | 激情欧美一区二区三区免费看 | 麻豆精品传媒视频 | 日韩激情久久 | 精品一区二区av | 国产精品久久久久久久婷婷 | 欧美色精品天天在线观看视频 | 91精品伦理 | www久久国产 | 成年人毛片在线观看 | 国产精选在线 | 四虎最新入口 | 日韩精品三区四区 | 婷婷国产视频 | 中文字幕av一区二区三区四区 | 99爱爱| 欧美福利精品 | 欧美在线久久 | 久久99久久99精品免费看小说 | 欧美专区日韩专区 | 日韩精品一区二区在线视频 | 国产一区二区三区免费观看视频 | 精品国产乱码 | 看毛片网站| 一级黄色片在线观看 | 干干夜夜 | 久久成人一区二区 | 日韩区视频 | 91麻豆精品国产91久久久无需广告 | 亚洲精品玖玖玖av在线看 | 黄色精品一区二区 | 国产精品video爽爽爽爽 | 国产精品视频线看 | 免费av片在线 | 亚洲精品美女在线观看播放 | 久久久久久久免费看 | 久久av电影 | 免费看久久久 | 国内精品福利视频 | 久久91久久久久麻豆精品 | 男女男视频| 91免费看片黄| 欧美日韩精品在线视频 | 亚洲狠狠婷婷综合久久久 | 成年人看片 | 青青五月天 | 国产精品二区在线观看 | 久久久精品一区二区 | 黄色www| 婷婷在线免费观看 | 五月婷婷六月丁香在线观看 | 免费的黄色av | 99精品久久精品一区二区 | 久久成人国产精品 | 国产高清福利在线 | 成人影视免费 | 国产69精品久久99不卡的观看体验 | 国内精品久久久精品电影院 | 高潮久久久久久久久 | 丁香六月av | 色欧美综合 | 国产99亚洲 | 美女网站一区 | 国产成人三级一区二区在线观看一 | 成人超碰在线 | 国产精品久久久久久电影 | 久久久国产视频 | 五月婷在线 | 成人影音在线 | www.久久色 | 亚洲欧洲成人精品av97 | av在线8| 婷婷六月中文字幕 | 婷婷av资源| av中文在线影视 | 成片视频免费观看 | 久久久国产精品人人片99精片欧美一 | 国产爽妇网 | 免费日韩高清 | 久久国语 | 色综合久久久久久久久五月 | 最近中文国产在线视频 | 色干干 | 日韩精品视频在线免费观看 | 国产美女被啪进深处喷白浆视频 | 久久久久久久久久久免费 | 在线观看国产成人av片 | 500部大龄熟乱视频使用方法 | 国产 一区二区三区 在线 | 狠狠的操狠狠的干 | 成人av片免费观看app下载 | 蜜臀久久99静品久久久久久 | 婷婷激情久久 | 久久久久久国产精品美女 | 午夜视频在线观看网站 | 国产精彩视频一区二区 | 91爱爱视频| 午夜久久久久久久久久久 | 91在线网址 | 色 免费观看 | 国产精品毛片一区 | 97视频在线观看成人 | 9992tv成人免费看片 | 日韩电影精品一区 | 国产99久久久国产精品 | 亚洲精品乱码久久久久久高潮 | 日韩在线观看小视频 | 视频高清 | 欧美色精品天天在线观看视频 | 三级黄色网络 | 最近最新最好看中文视频 | 色婷婷成人网 | 国产黄色大片 | 日韩激情视频在线观看 | 精品久久久久久久久久久久久久久久 | av亚洲产国偷v产偷v自拍小说 | 日本中文字幕在线看 | 狠狠操在线 | 国产精品人人做人人爽人人添 | 天天综合网久久 | 久久资源总站 | 日韩欧美精品在线观看 | 欧美激情操 | 欧美日韩首页 | 人人干天天射 | 美女视频永久黄网站免费观看国产 | 久久久久高清 | 2022久久国产露脸精品国产 | 久久99精品久久久久久三级 | 91av视频| 免费视频在线观看网站 | 免费看污黄网站 | 成人精品国产免费网站 | 91亚洲精品乱码久久久久久蜜桃 | 国产精品久久久久久久久久白浆 | 午夜国产一区二区三区四区 | 亚洲欧洲精品在线 | 成人av在线网 | 久久免费公开视频 | 青青草视频精品 | 福利电影久久 | 久久免费视频8 | 色国产精品一区在线观看 | 视频一区二区在线观看 | 最近中文字幕免费视频 | 天天草天天草 | 天天拍夜夜拍 | 日韩免费一区二区三区 | 中文字幕在线一区观看 | 亚洲色图美腿丝袜 | 在线观看韩日电影免费 | 精品亚洲欧美无人区乱码 | 亚洲三级国产 | 97av精品| 国产在线色视频 | 国产经典av | 欧美日韩综合在线 | 一级片免费观看 | 全久久久久久久久久久电影 | 97av在线| 三级黄色理论片 | 国产精品美女久久久久久 | 国产精品淫片 | 天天色.com | 日韩深夜在线观看 | 国产亚洲成av人片在线观看桃 | 综合色综合色 | 一区二区三区在线观看 | 中文字幕一区二区三区四区 | 日韩激情在线 | 亚洲综合在线五月天 | av综合在线观看 | 久视频在线 | 精品产品国产在线不卡 | 日韩精品欧美视频 | 欧美精品久久99 | 天天躁日日躁狠狠躁av中文 | 一区二区三区在线免费观看 | 免费看黄色小说的网站 | 日韩中文免费视频 | 久草视频在线资源 | 国产一区成人在线 | 日一日干一干 | 亚洲欧美日本A∨在线观看 青青河边草观看完整版高清 | 欧美日韩午夜在线 | 天天综合五月天 | 一区二区三区日韩精品 | 国产欧美精品一区二区三区 | 字幕网资源站中文字幕 | 日韩r级在线 | 国产精品久久影院 | 免费日韩一级片 | 精品国产伦一区二区三区免费 | 激情综合中文娱乐网 | 夜夜操狠狠干 | 亚洲精品在线播放视频 | 午夜婷婷在线播放 | 黄色软件视频大全免费下载 | 欧美国产一区在线 | 国产精品久久久久久久久久直播 | 蜜臀av性久久久久av蜜臀妖精 | 成人亚洲综合 | 偷拍精偷拍精品欧洲亚洲网站 | 丁香激情综合久久伊人久久 | 欧美日韩亚洲国产一区 | 日韩首页| 久久人人爽爽人人爽人人片av | 日韩特级片 | 久久国产精品一区二区 | 人人看人人草 | 九色最新网址 | 一级免费片| 夜色成人网 | 免费av在 | 99视频精品视频高清免费 | 久草久草在线观看 | 亚州av成人 | 91人人澡人人爽人人精品 | 亚洲aaa毛片 | 中文字幕婷婷 | 99久久精品久久亚洲精品 | 国产精品理论片在线播放 | 亚洲免费在线播放视频 | 亚洲一区二区精品视频 | 国产精品久久嫩一区二区免费 | 五月花丁香婷婷 | 国产一级片不卡 | 欧美三人交 | 欧美性黑人 | 亚洲精品午夜久久久久久久 | 四虎在线观看 | 亚洲五月综合 | 香蕉手机在线 | 国产一区高清在线 | 精品一区二区综合 | 精品国产乱码久久久久久1区2匹 | 国产精品一区二区在线观看免费 | 日本一区二区高清不卡 | 成人性生交视频 | a在线播放| 国产美女免费观看 | 久久久国产网站 | 五月天亚洲综合 | 正在播放国产一区 | 91在线视频观看免费 | 日韩亚洲欧美中文字幕 | 久久综合九色综合网站 | 成人在线免费小视频 | 久久99视频 | 九七视频在线观看 | 久久国产乱 | 激情片av | 久久免费视频这里只有精品 | 日韩在线观看中文字幕 | 国产成人精品一区二区三区免费 | 国产剧情一区二区 | 日日日日 | 精品av在线播放 | av大全在线免费观看 | 中文字幕av免费在线观看 | 中文字幕高清在线播放 | 成人三级视频 | 66av99精品福利视频在线 | 91亚色免费视频 | 天天操综合 | 2019av在线视频 | 亚洲精品国产精品久久99热 | 亚洲欧美精品在线 | 国产第页 | 69国产盗摄一区二区三区五区 | 日韩精品中文字幕有码 | 91视频这里只有精品 | 成人欧美亚洲 | 国产精品久久久久国产精品日日 | www.狠狠干 | 四虎影视久久久 | 天天激情天天干 | 亚洲精品一区二区久 | 六月色婷婷 | 国产亚洲婷婷 | 免费能看的黄色片 | 综合网在线视频 | 成人av高清 | 日本巨乳在线 | 久久69精品久久久久久久电影好 | 婷婷色网视频在线播放 | 国产一级黄大片 | 18网站在线观看 | 国产精品美女久久久久久免费 | 中文字幕观看av | 久久综合久久鬼 | 国产精品成人aaaaa网站 | 国产麻豆果冻传媒在线观看 | 人人超碰在线 | 国产精品视频在线看 | 日韩精品91偷拍在线观看 | 天天射天天爱天天干 | 91av精品 | 精品电影一区二区 | 免费av黄色 | 亚洲区另类春色综合小说校园片 | 国产黄视频在线观看 | 中文字幕在线视频一区二区 | 狠狠干综合网 | 国产又粗又猛又爽 | 国产日韩精品一区二区 | 国产一区二区三区四区大秀 | 美女黄视频免费看 | 色999视频 | 国产精品系列在线播放 | 友田真希av | 日本电影黄色 | 国产精品免费在线视频 | 新av在线 | 91在线观看视频 | 精品国产综合区久久久久久 | 91在线在线观看 | 国产成人精品一区二区三区在线 | 日韩精品在线视频 | ,久久福利影视 | 97超级碰碰碰碰久久久久 | 91在线免费播放视频 | 久久蜜桃av | 国产福利av在线 | 亚洲午夜久久久久久久久久久 | 婷婷色狠狠 | 亚洲欧美va | 久久精品久久久精品美女 | 天天色婷婷 | 97视频亚洲 | 国产一区二区三区在线 | 国产亚洲精品bv在线观看 | 九九三级毛片 | 免费观看高清 | 狠狠狠色丁香婷婷综合久久88 | 8x成人在线 | 成人小视频在线播放 | 久久视频在线观看免费 | www.888av| av一区在线| 免费能看的黄色片 | 免费亚洲婷婷 | 免费日韩视频 | 久草资源免费 | 国产一区二区中文字幕 | 麻豆小视频在线观看 | 黄色一级影院 | 久久视精品 | 一区二区精品久久 | 国产污视频在线观看 | 一级黄色片网站 | 国产区精品在线 | 国产免费久久 | 亚洲天天在线日亚洲洲精 | 国产小视频在线观看 | 在线观看aa | 在线观看网站黄 | 91免费黄视频 | 国产一区免费在线观看 | 日韩视频免费在线 | 在线观看av小说 | 国产成人精品一区二区三区网站观看 | 日韩69av| 91久久精品一区二区三区 | 精品国产亚洲一区二区麻豆 | 92中文资源在线 | 久久国产精品视频 | 99色在线播放 | 精品夜夜嗨av一区二区三区 | 久久精品91久久久久久再现 | 日本精品一区二区三区在线播放视频 | 日韩免费二区 | 一区二区日韩av | 天天操综合网 | 一区二区三区免费在线 | 日韩三级在线观看 | 婷婷伊人五月天 | 亚洲狠狠| 亚洲欧洲精品一区 | 国产在线精品一区二区 | 久草在线久 | 91精品国产九九九久久久亚洲 | 夜夜躁狠狠燥 | 国产精品 999| 久久久久国产精品免费网站 | 人成电影网 | 国产一级电影在线 | 三级av在线免费观看 | 日韩亚洲国产精品 | 欧美日韩1区 | 久99久久| 国产97在线看 | 探花视频在线观看免费版 | 在线国产视频 | 在线免费观看的av网站 | 亚洲午夜精品在线观看 | 在线看成人av | 欧美精品久久99 | 一级黄色电影网站 | 99一级片| 少妇bbb搡bbbb搡bbbb | 天天色.com | 久久国产品 | 亚洲精品国产精品国产 | 91香蕉视频好色先生 | 97超碰在线久草超碰在线观看 | 青青草国产精品 | 97**国产露脸精品国产 | 黄色在线观看网站 | 9i看片成人免费看片 | 激情五月伊人 | 欧美在线观看视频一区二区三区 | 91在线观看欧美日韩 | 日韩黄在线观看 | 欧美日韩国产精品一区二区三区 | 特黄特色特刺激视频免费播放 | 99久久精品免费看国产一区二区三区 | 日韩伦理片hd| 国产只有精品 | 国产精品综合久久 | 久久伊人国产精品 | 麻豆成人在线观看 | 手机看片 | 91在线www | 黄色在线观看污 | 亚洲午夜久久久久久久久 | 人人爽人人爽人人片av | 亚洲女同ⅹxx女同tv | 日韩av手机在线观看 | 国产精品色婷婷视频 | 蜜桃视频在线观看一区 | 91精品啪在线观看国产线免费 | 亚州日韩中文字幕 | 中文在线字幕免费观看 | 国产999精品久久久久久绿帽 | 日韩精品你懂的 | 久久久久久激情 | 99re久久资源最新地址 | 久久tv| 成人黄色免费在线观看 | 手机看片中文字幕 | 日韩视频1区| 国产在线97 | 亚洲综合视频在线观看 | 久久999精品| 99精品国产成人一区二区 | 玖玖国产精品视频 | 欧美亚洲成人xxx | 久久影院中文字幕 | 国产玖玖在线 | 欧美韩日视频 | 日韩av中文在线 | 最新av免费在线 | av一区二区三区在线播放 | 亚洲免费成人 | 久久av不卡 | 一区二区三区精品久久久 | 一级a性色生活片久久毛片波多野 | 国产精品久久久久久一区二区 | 亚洲成人在线免费 | 成人h电影| 婷婷丁香在线视频 | 亚洲精品福利视频 | 久久综合九色欧美综合狠狠 | 中文在线字幕观看电影 | 精品福利国产 | 碰天天操天天 | 亚洲精品视频网址 | 免费电影一区二区三区 | av电影中文字幕在线观看 | aa一级片| 久久免费看毛片 | 亚洲精品456在线播放乱码 | 亚洲伦理一区二区 | 狠狠天天 | 欧美精品999| 精品国产乱码久久久久久久 | 国内视频在线 | 999久久久久久 | 玖玖精品在线 | 国产91精品在线播放 | 亚洲高清免费在线 | 亚洲va欧美 | 天天射天天舔天天干 | 国产精品成人av电影 | 亚洲综合成人婷婷小说 | 美女网站久久 | 91桃色在线播放 | 亚洲精品ww| 久久久久久高潮国产精品视 | 国产亚洲精品久久久久久久久久久久 | 色欧美视频 | 亚洲在线成人精品 | 中文字幕免费高清 | 视频一区在线播放 | av在线影视 | 色偷偷男人的天堂av | 国产精品免费久久 | 国产免费大片 | 国产精品99久久久久人中文网介绍 | 亚洲精品18日本一区app | 精品欧美一区二区精品久久 | 天天插视频 | av丝袜在线 | 国产91综合一区在线观看 | 久久综合偷偷噜噜噜色 | 69亚洲视频 | 久久国产精品免费看 | 欧美亚洲精品一区 | 久久久毛片 | 欧美色一色| 久热爱 | 成在线播放 | 麻豆影视网 | 亚洲国产精品女人久久久 | 激情综合站 | 国产在线一区二区三区播放 | 国产成人亚洲在线电影 | 国产亚洲成人网 | 西西444www大胆高清视频 | 麻豆94tv免费版 | 国产精品国产亚洲精品看不卡15 | 亚州人成在线播放 | 国产精品小视频网站 | 色婷婷精品大在线视频 | 欧美久久久久久久久久 | 337p日本欧洲亚洲大胆裸体艺术 | 国产精品久久久久久久久久了 | 91视频电影 | 99久久er热在这里只有精品66 | 色综合久久网 | 欧美美女视频在线观看 | 91免费版在线观看 | 亚洲精品中文在线资源 | 国精产品一二三线999 | 最近中文字幕国语免费高清6 | 一级黄色免费网站 | 天天玩天天操天天射 | 91中文字幕视频 | 色婷婷在线观看视频 | 久久免费视频3 | 三上悠亚一区二区在线观看 | 日本成址在线观看 | 狠狠躁日日躁狂躁夜夜躁av | 日韩免费一二三区 | 欧美性超爽 | 不卡的av在线 | 成人免费视频视频在线观看 免费 | 在线观看成人福利 | av在线成人 | 久久视频免费在线观看 | 91精品区 | 在线观看一级视频 | 日韩精品一区二区三区免费观看视频 | 黄色小说在线观看视频 | 四虎国产精品免费观看视频优播 | 夜夜躁日日躁狠狠久久av | 色婷婷久久久 | 久久精品一区八戒影视 | 久久国产亚洲视频 | 久久免费久久 | 亚洲精品一区二区三区四区高清 | 丁香五月亚洲综合在线 | 人人干在线 | 91福利视频网站 | 午夜电影一区 | 国产精品九色 | 国产精品色婷婷视频 | 亚洲日韩中文字幕在线播放 | 免费观看一区二区三区视频 | 国产成人a亚洲精品 | 久久只精品99品免费久23小说 | 91成人在线视频观看 | 久久99亚洲精品久久久久 | 岛国大片免费视频 | 国产在线不卡精品 | 日韩在线观看网址 | 国产黄色a| 亚洲精品www久久久久久 | 日韩在线视频网站 | 香蕉视频网址 | 亚洲女在线 | 黄色一级片视频 | 国产人免费人成免费视频 | 色 免费观看 | 特级西西人体444是什么意思 | 欧美一级片播放 | 亚洲在线视频观看 | 天堂av在线 | 久久这里只精品 | 日日夜夜天天 | 久久爱导航 | 亚洲成年人免费网站 | 黄色成人小视频 | 人人干在线 | 亚洲理论视频 | 色全色在线资源网 | 91亚色视频 | 国产探花 | 国产丝袜| www.超碰97.com | 超碰97人人爱 | 成人黄色大片 | 午夜10000| 亚洲一区二区三区精品在线观看 | 天天干亚洲 | 亚洲午夜av电影 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 麻豆免费看片 | 免费精品视频在线观看 | 日韩在线观看第一页 | 九九热精品视频在线观看 | 中文高清av | 中文字幕精品www乱入免费视频 | 免费三级黄色 | 在线观看成人一级片 | 国产又粗又硬又爽的视频 | 人人爽人人澡 | 午夜12点 | 亚洲国产mv | 久久久免费视频播放 | 免费日韩一区二区三区 | 三级黄色免费 | 18久久久久| 夜夜夜影院 | 成年人app网址 | 亚洲成人软件 | 狠狠色丁香九九婷婷综合五月 | 成人午夜电影在线 | 欧美一区二区三区在线播放 | 国产精品久久久久久久久久久不卡 | 在线小视频你懂得 | 中文字幕第一页在线 | 日韩美在线 | 国内精品久久久久影院优 | 精品国产一区二区三区在线 | 中文字幕日韩免费视频 | av大全在线观看 | 亚洲小视频在线观看 | 色停停五月天 | 99色免费 | 久草电影在线观看 | 中文av不卡| 欧美亚洲一区二区在线 | 国产理论在线 | 日韩在线精品一区 | 香蕉国产91| 国产99久久九九精品免费 | 在线黄网站| 黄色成人av| av手机版| 粉嫩一二三区 | 9999国产精品 | 国产原创av在线 | 涩av在线 | 日韩高清av | 99se视频在线观看 | 99精品视频中文字幕 | 狠狠狠色狠狠色综合 | 日韩激情在线视频 | 亚洲理论在线 | 久久激情五月激情 | 国产又粗又硬又长又爽的视频 | 久久午夜免费观看 | 成人精品福利 | 美女很黄免费网站 | 在线播放视频一区 | 日韩电影中文字幕在线观看 | 视频在线观看一区 | 干亚洲少妇| 激情网五月天 | 日韩在线电影观看 | 久久夜夜操| 伊人五月综合 | 91麻豆精品久久久久久 | 91av视频在线观看 | 日韩动漫免费观看高清完整版在线观看 | 国产一区二区不卡在线 | 色婷婷天天干 | 天堂网一区 | 蜜臀久久99精品久久久无需会员 | 91精品国产99久久久久久久 | 色综合天 | 在线观看片 | 黄色小说在线免费观看 | 毛片在线播放网址 | 中文字幕在线视频一区二区三区 | 在线播放国产精品 | 国产经典av | 欧美日韩国语 | 免费涩涩网站 | 六月丁香激情综合色啪小说 | 欧美成天堂网地址 | 婷婷在线网 | 日韩成人免费在线 | 国产激情小视频在线观看 | 深爱婷婷久久综合 | 伊人色综合久久天天 | 国产美女被啪进深处喷白浆视频 | 久草视频在线新免费 | 久久精品高清 | 成人一区二区在线观看 | 国产亚洲一级高清 | 免费色视频网站 | 色黄视频免费观看 | 国产一区私人高清影院 | 午夜久久美女 | 国产精品国产三级国产aⅴ9色 | 精品黄色在线 | 精品久久久久久综合日本 | 97人人模人人爽人人喊网 | 亚洲不卡123| 成av人电影| 久久综合九色欧美综合狠狠 | www久久精品 | 亚洲精品视频第一页 | 久久精品毛片 | 91香蕉视频污在线 | 天天玩天天干天天操 | 日韩精品五月天 | 久久久久久久久毛片 | 亚洲欧美日韩中文在线 | 奇米影视777四色米奇影院 | 亚洲日本在线一区 | 美女网站在线播放 | 国产精品不卡在线 | 在线观看精品黄av片免费 | 麻豆果冻剧传媒在线播放 | 成片免费观看视频大全 | 国产精品久久久久一区 | 国产一级在线看 | 欧美成人在线网站 | 久久av电影 | 日韩电影在线视频 | 久久免费的精品国产v∧ | 欧日韩在线视频 | 2021久久| 国产精品一区二区av | 日韩在线第一区 | 国产精彩视频一区 | 日日夜av| 久久呀| 亚洲 欧洲av | 久草在线视频看看 | 黄色特级一级片 | 免费在线一区二区 | 夜夜骑首页 | 亚洲日日射 | 日韩一区二区三区免费视频 | 久久永久免费 | 亚洲欧美国产精品久久久久 | 狠狠干夜夜 | 国产黄色免费电影 | 成年人免费在线观看网站 | 久久视频在线观看中文字幕 | 综合天天久久 | 国产综合小视频 | 精品专区一区二区 | av片在线看 | 伊人天堂网 | 中文字幕 国产精品 | 91丨九色丨91啦蝌蚪老版 | 99久久精品午夜一区二区小说 | 麻豆视频观看 | 欧美永久视频 | 久久狠狠婷婷 | 91在线最新 | www狠狠| 狠狠色丁香婷婷综合久小说久 | 97手机电影网 | 全黄网站 | 在线观看的a站 | 国产又粗又猛又色又黄视频 | 色资源网在线观看 | 91麻豆精品国产91久久久无限制版 | 亚洲精品玖玖玖av在线看 | 色国产精品 | 国产一区二三区好的 | 国产99久久久欧美黑人 | www久久99| 999视频在线播放 | 91豆花在线观看 | 日日干美女 | 天天射天天操天天干 | 午夜av免费在线观看 | 国产精品6 | 成人一区电影 | 久久999久久 | 免费福利视频导航 | 在线观看的a站 | 亚洲伊人成综合网 | 日韩av中文 | 天天天插 | 婷婷午夜天 | 五月天久久久久久 | 日本三级国产 | 久草电影网 | 成年一级片 | 成人久久免费视频 | 免费观看成人网 | 99久久精品国产毛片 | 免费能看的黄色片 | 91精品一区在线观看 | 国产免费又粗又猛又爽 | 一区在线观看 | adn—256中文在线观看 | 国产精品一区二区三区久久久 | 国产精品人成电影在线观看 | 中文综合在线 | 国产精品3 | 久久久久久久av麻豆果冻 | 色99色| 久艹在线播放 | 在线观看中文字幕dvd播放 | 96久久久| 中文字幕乱在线伦视频中文字幕乱码在线 | 国产理论影院 | 色婷婷国产精品一区在线观看 | 五月天色综合 | 在线观看www91 | 深夜国产福利 | 五月花丁香婷婷 | 99精品在线免费在线观看 | 91成人短视频在线观看 | 女人魂免费观看 | 亚洲精品高清在线 | 亚洲国产精品va在线 | www久草 | 午夜视频日本 | 91超国产 | 国产精品v欧美精品v日韩 | 天天天射 | 波多野结衣在线观看视频 | 97精品国产97久久久久久粉红 | 国产精品亚洲片在线播放 | 久久久久久中文字幕 | 国产在线污 | 粉嫩av一区二区三区四区 | 亚洲午夜精品久久久久久久久 | 精品专区一区二区 | 久久se视频 | 美女激情影院 | 亚洲欧洲国产精品 | 手机看片久久 | 中文av资源站 | 久草.com| 中文字幕传媒 | 一级免费片 | 欧美一区二区精品在线 | 狠狠狠操 | 91亚洲网 | 综合色站导航 | 夜夜操网站| 国产精品中文 | 国产精久久久 | 久久久久影视 | 热久久免费视频 | 中文字幕在线观看免费 | 欧美色就是色 | 国产福利a | 美女很黄免费网站 | www.狠狠操.com | 日韩欧美电影网 | 欧美看片| 国产一级久久 | 一区在线观看视频 | 日韩在线免费看 | 国产亚洲精品久久久久久无几年桃 | 天天操夜夜操国产精品 | 四虎影视8848dvd | 成+人+色综合 | 91视视频在线直接观看在线看网页在线看 | 激情综合网五月激情 | 中文字幕免费成人 | 精品国产一区二区三区不卡 | 免费国产黄线在线观看视频 | 九月婷婷色 | 亚洲精品视频在 | 精精国产xxxx视频在线播放 | 日本中文一级片 | 综合色综合 | 97网在线观看 | 久草在线免 | 免费看一级片 | 亚洲精品h | av黄免费看 | www.婷婷com | 免费网站在线观看人 | 91成人免费视频 | 极品久久久久 | 天堂视频中文在线 | 婷婷国产精品 | 激情久久久久 | 蜜臀久久99静品久久久久久 | 在线观看国产日韩 | 欧美精品三级在线观看 | 麻豆视频免费在线播放 | 毛片播放网站 | 激情网站免费观看 | av电影 一区二区 | 国产视频一区二区在线播放 | 久久se视频 | 国产小视频国产精品 | 97精品国产91久久久久久 | 偷拍区另类综合在线 | 激情深爱.com | 国产九九九视频 | 亚洲天堂精品视频在线观看 | 国产精品一区二区三区免费视频 | 黄色小网站免费看 | 一本色道久久精品 | 久久国产经典视频 | 亚洲免费精品一区二区 | 在线视频国产区 | 日本一区二区免费在线观看 | 国模视频一区二区三区 | www蜜桃视频 | 天天操天天干天天摸 | 天天色天天综合网 | 日韩免费电影 | 天天草天天草 | 狠狠狠狠狠色综合 | 国产福利免费看 | 超碰个人在线 | 日韩高清在线一区 | 国产在线视频资源 | 在线视频 国产 日韩 | 婷婷久久亚洲 |