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

歡迎訪問 生活随笔!

生活随笔

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

asp.net

单例设计模式-静态内部类-基于类初始化的延迟加载解决方案及原理解析

發布時間:2024/4/13 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单例设计模式-静态内部类-基于类初始化的延迟加载解决方案及原理解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

剛剛線程1看不到線程0的重排序,我們創建一個類,這個方案是使用靜態內部類來解決,一會我們也會分析一下原理,我們創建一個靜態內部類,靜態內部類的代理模式,JVM在類的初始化階段,也就是class被加載后,并且被線程使用之前,都是類的初始化階段,在這個階段會執行類的初始化,那在執行類的初始化期間呢,JVM會去獲取一個鎖,這個鎖可以同步多個線程,對一個類的初始化,也就是綠色的部分,基于這個特性,我們可以實現基于內部類的并且是線程安全的,延遲初始化方案,那我們看一下這個圖,還是線程0和線程1,藍色和紅色,那在這種實現模式中呢,對于右側的2和3,也就是橙色的框,這兩個步驟的重排序,對于我們前面講的,線程1并不會看到,也就是說,非構造線程是不允許看到重排序的,因為我們之前是講的線程0來構造這個單例對象,初始化一個類,包括執行類的靜態初始化,還有初始化在這個類中聲明的靜態變量,根據JAVA語言規范,主要分5種情況,首次發生的時候呢,一個類將被立刻初始化,這里所說的類呢,泛指包括接口interface,也是一個類,那假設這個類是A,那現在我們說一下,這幾種情況,都會導致這個A類,被立刻初始化,首先呢第一種情況,有一個A類型的實例被創建,A類型中的一個靜態方法被調用,第三種情況呢,是A類中聲明的一個靜態成員,被賦值,第四種情況,A類中聲明的一個靜態成員被使用,并且這個成員不是一個常量成員,前四種我們實際工作中用的比較多,第五種用的比較少,也就是說如果A類是一個頂級類,關于頂級類在JAVA語言規范里面的介紹,并且呢在這個類中,有嵌套的斷言語句,這種情況呢A類也會立刻被初始化,也就是說剛剛說的五種情況,前四種是我們經常會被碰到的,只要首次發生以上說的一個情況,這個類就會被立刻初始化,把我們看一下這個圖,當線程0和線程1試圖想獲取這個鎖的時候,也就是獲得class對象的初始化鎖,這個時候肯定只有一個線程能獲得這個鎖,假設線程0獲得這個鎖了,線程0執行內部類的一個初始化,對于靜態內部類即使23之間存在重排序,但是線程1是無法看到這個重排序的,因為這里有一個class對象的初始化鎖,因為這里面有鎖,對于線程0而言,初始化這個靜態內部類的時候,也就是把這個instance new出來,可以看到我們這里還有一個大框,所以23怎么排序無所謂,線程1看不到,因為線程1在綠色區域等待著,所以靜態內部類就是基于類初始化的延遲加載解決方案,那我們回到代碼里 package com.learn.design.pattern.creational.singleton;/*** 前面說了我們使用靜態內部類* * 所以靜態內部類核心在于* InnerClass類的初始化鎖* 看哪個線程拿到* 哪個線程就去初始化他* 對于這種情況呢* 我們來測試一下* 打開我們的線程類* 還是用多線程來測試* * 非常重要的一點* 我們沒有寫私有的構造函數* * * @author Leon.Sun**/ public class StaticInnerClassSingleton {/*** 這個class要聲明成private的class* 權限一定要控制好* * * @author Leon.Sun**/private static class InnerClass{/*** 那這里聲明一個什么呢* 這個名字還是用類名來做* new一個StaticInnerClassSingleton* 那在這個靜態內部類里邊直接new了一個StaticInnerClassSingleton這個類的對象* 并且它是private和static的* * */private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();}/*** 那我們要開放獲取這個對象的方法* 所以是public的* 返回值肯定是StaticInnerClassSingleton* return什么呢* 通過這個靜態內部類InnerClass點靜態的成員staticInnerClassSingleton* 那這個靜態內部類的單例模式就完成了* 非常簡單* 那我們講一下原理* 我們看一下圖* * * @return*/public static StaticInnerClassSingleton getInstance(){return InnerClass.staticInnerClassSingleton;}/*** 私有的構造器肯定是要有的* 否則外部就可以new出來了* 所以這一點千萬不要忘記* 如果之前寫的時候沒有發現這個問題的話* 對聲明構造器一定要加深* 現在我們來到Test直接run一下* 我們可以看到線程0和線程1拿到的是同一個* 因為這個方式非常簡單* 就不debug了* 靜態內部類和簽名的doublecheck* 都是為了做延遲初始化* 來降低創建單例實例的開銷* 所以具體在業務場景中采用什么方案呢* 還要看我們的單例對象* 是什么樣的* 另外一點* 如果問設計模式* 單例模式會被百分之九十九問到* 那么單例模式剛剛講的這一種方案* 一定要理解透* 這個是一個循序漸進的過程* 而且單例模式非常重要* 如果可以一層一層迭代* 希望對著兩種方案和思路來引入靜態內部類和doublecheck一步一步解決什么問題* 可以自己回顧一下* 總結一下* * * */private StaticInnerClassSingleton(){if(InnerClass.staticInnerClassSingleton != null){throw new RuntimeException("單例構造器禁止反射調用");}} } package com.learn.design.pattern.creational.singleton;public class T implements Runnable {@Overridepublic void run() { // LazySingleton lazySingleton = LazySingleton.getInstance(); // System.out.println(Thread.currentThread().getName()+" "+lazySingleton); // LazyDoubleCheckSingleton instance = LazyDoubleCheckSingleton.getInstance();/*** 通過這個類的getInstance方法* 看上去沒有什么區別* 但是里面使用的是靜態內部類* 而且是一個private的* */StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();;// ContainerSingleton.putInstance("object",new Object()); // Object instance = ContainerSingleton.getInstance("object"); // ThreadLocalInstance instance = ThreadLocalInstance.getInstance();System.out.println(Thread.currentThread().getName()+" "+instance);} } package com.learn.design.pattern.creational.singleton;import java.io.IOException; import java.lang.reflect.InvocationTargetException;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { // LazySingleton lazySingleton = LazySingleton.getInstance();// System.out.println("main thread"+ThreadLocalInstance.getInstance()); // System.out.println("main thread"+ThreadLocalInstance.getInstance()); // System.out.println("main thread"+ThreadLocalInstance.getInstance()); // System.out.println("main thread"+ThreadLocalInstance.getInstance()); // System.out.println("main thread"+ThreadLocalInstance.getInstance()); // System.out.println("main thread"+ThreadLocalInstance.getInstance());Thread t1 = new Thread(new T());Thread t2 = new Thread(new T());t1.start();t2.start();System.out.println("program end");// HungrySingleton instance = HungrySingleton.getInstance(); // EnumInstance instance = EnumInstance.getInstance(); // instance.setData(new Object()); // // ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file")); // oos.writeObject(instance); // // File file = new File("singleton_file"); // ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); //HungrySingleton newInstance = (HungrySingleton) ois.readObject(); // EnumInstance newInstance = (EnumInstance) ois.readObject(); // // System.out.println(instance.getData()); // System.out.println(newInstance.getData()); // System.out.println(instance.getData() == newInstance.getData());// Class objectClass = HungrySingleton.class; // Class objectClass = StaticInnerClassSingleton.class;// Class objectClass = LazySingleton.class; // Class objectClass = EnumInstance.class;// Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class); // // constructor.setAccessible(true); // EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);// // LazySingleton newInstance = (LazySingleton) constructor.newInstance(); // LazySingleton instance = LazySingleton.getInstance();// StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance(); // StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();// HungrySingleton newInstance = (HungrySingleton) constructor.newInstance(); // HungrySingleton instance = HungrySingleton.getInstance();// System.out.println(instance); // System.out.println(newInstance); // System.out.println(instance == newInstance);// EnumInstance instance = EnumInstance.getInstance(); // instance.printTest();} }

?

總結

以上是生活随笔為你收集整理的单例设计模式-静态内部类-基于类初始化的延迟加载解决方案及原理解析的全部內容,希望文章能夠幫你解決所遇到的問題。

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