日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

享元模式在JDK源码中的应用——Java设计模式系列学习笔记

發布時間:2024/2/28 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 享元模式在JDK源码中的应用——Java设计模式系列学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. String中的享元模式

Java中將String類定義為final(不可改變的),JVM中字符串一般保存在字符串常量池中,java會確保一個字符串在常量池中只有一個拷貝,這個字符串常量池在JDK6.0以前是位于常量池中,位于永久代,而在JDK7.0中,JVM將其從永久代拿出來放置于堆中。

我們做一個測試:

public class Main {public static void main(String[] args) {String s1 = "hello";String s2 = "hello";String s3 = "he" + "llo";String s4 = "hel" + new String("lo");String s5 = new String("hello");String s6 = s5.intern();String s7 = "h";String s8 = "ello";String s9 = s7 + s8;System.out.println(s1==s2);//trueSystem.out.println(s1==s3);//trueSystem.out.println(s1==s4);//falseSystem.out.println(s1==s9);//falseSystem.out.println(s4==s5);//falseSystem.out.println(s1==s6);//true} }

String類的final修飾的,以字面量的形式創建String變量時,jvm會在編譯期間就把該字面量hello放到字符串常量池中,由Java程序啟動的時候就已經加載到內存中了。這個字符串常量池的特點就是有且只有一份相同的字面量,如果有其它相同的字面量,jvm則返回這個字面量的引用,如果沒有相同的字面量,則在字符串常量池創建這個字面量并返回它的引用。

由于s2指向的字面量hello在常量池中已經存在了(s1先于s2),于是jvm就返回這個字面量綁定的引用,所以s1==s2。

s3中字面量的拼接其實就是hello,jvm在編譯期間就已經對它進行優化,所以s1和s3也是相等的。

s4中的new String("lo")生成了兩個對象,hel,new String("lo"),hel存在字符串常量池,new String("lo")存在堆中,String s4 = "hel" + new String("lo")實質上是兩個對象的相加,編譯器不會進行優化,相加的結果存在堆中,而s1存在字符串常量池中,當然不相等。s1==s9的原理一樣。

s4==s5兩個相加的結果都在堆中,不用說,肯定不相等。

s1==s6中,s5.intern()方法能使一個位于堆中的字符串在運行期間動態地加入到字符串常量池中(字符串常量池的內容是程序啟動的時候就已經加載好了),如果字符串常量池中有該對象對應的字面量,則返回該字面量在字符串常量池中的引用,否則,創建復制一份該字面量到字符串常量池并返回它的引用。因此s1==s6輸出true。

2. Integer 中的享元模式

使用例子如下:

public static void main(String[] args) {Integer i1 = 12 ;Integer i2 = 12 ;System.out.println(i1 == i2);Integer b1 = 128 ;Integer b2 = 128 ;System.out.println(b1 == b2); }

輸出:

true false

為什么第一個是true,第二個是false?
反編譯后可以發現 Integer b1 = 128; 實際變成了 Integer b1 = Integer.valueOf(128);,所以我們來看 Integer 中的 valueOf 方法的實現

public final class Integer extends Number implements Comparable<Integer> {public static Integer valueOf(int var0) {return var0 >= -128 && var0 <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[var0 + 128] : new Integer(var0);}//...省略... }

IntegerCache 緩存類

//是Integer內部的私有靜態類,里面的cache[]就是jdk事先緩存的Integer。 private static class IntegerCache {static final int low = -128;//區間的最低值static final int high;//區間的最高值,后面默認賦值為127,也可以用戶手動設置虛擬機參數static final Integer cache[]; //緩存數組static {// high value may be configured by propertyint h = 127;//這里可以在運行時設置虛擬機參數來確定h :-Djava.lang.Integer.IntegerCache.high=250String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {//用戶設置了int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);//雖然設置了但是還是不能小于127// 也不能超過最大值h = Math.min(i, Integer.MAX_VALUE - (-low) -1);}high = h;cache = new Integer[(high - low) + 1];int j = low;//循環將區間的數賦值給cache[]數組for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);}private IntegerCache() {} }

可以看到 Integer 默認先創建并緩存 -128 ~ 127 之間數的 Integer 對象,當調用 valueOf 時如果參數在 -128 ~ 127 之間則計算下標并從緩存中返回,否則創建一個新的 Integer 對象

public final class Long extends Number implements Comparable<Long> {public static Long valueOf(long var0) {return var0 >= -128L && var0 <= 127L ? Long.LongCache.cache[(int)var0 + 128] : new Long(var0);} private static class LongCache {private LongCache(){}static final Long cache[] = new Long[-(-128) + 127 + 1];static {for(int i = 0; i < cache.length; i++)cache[i] = new Long(i - 128);}}//... }

同理,Long 中也有緩存,不過不能指定緩存最大值

3. Apache Commons Pool2中的享元模式

對象池化的基本思路是:將用過的對象保存起來,等下一次需要這種對象的時候,再拿出來重復使用,從而在一定程度上減少頻繁創建對象所造成的開銷。用于充當保存對象的“容器”的對象,被稱為“對象池”(Object Pool,或簡稱Pool)

Apache Commons Pool實現了對象池的功能。定義了對象的生成、銷毀、激活、鈍化等操作及其狀態轉換,并提供幾個默認的對象池實現。

有幾個重要的對象:

  • PooledObject(池對象):用于封裝對象(如:線程、數據庫連接、TCP連接),將其包裹成可被池管理的對象。
  • PooledObjectFactory(池對象工廠):定義了操作PooledObject實例生命周期的一些方法,PooledObjectFactory必須實現線程安全。
  • Object Pool (對象池):Object Pool負責管理PooledObject,如:借出對象,返回對象,校驗對象,有多少激活對象,有多少空閑對象。
// 對象池private final Map<S, PooledObject<S>> allObjects = new ConcurrentHashMap<S, PooledObject<S>>();

重要方法:

borrowObject:從池中借出一個對象。
returnObject:將一個對象返還給池。

總結

以上是生活随笔為你收集整理的享元模式在JDK源码中的应用——Java设计模式系列学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。