單例模式(構造器私有)
單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一,有以下特點:
-
單例類只能有一個實例。
-
單例類必須自己創建自己的唯一實例。
-
單例類必須給所有其他對象提供這一實例。
反射可以破壞單例模式!!!
餓漢式
這種方式比較常用,但容易產生垃圾對象 優點:沒有加鎖,執行效率會提高。 缺點:類加載時就初始化,浪費內存。
?
package com.lyc.single;//餓漢式單例public class Hungry {//可能會浪費空間private byte[] bytes1= new byte[1024*1024];private byte[] bytes2= new byte[1024*1024];private byte[] bytes3= new byte[1024*1024];private byte[] bytes4= new byte[1024*1024];private Hungry(){?}private static final Hungry instance = new Hungry();//創建對象public static Hungry getInstance(){return instance;}}
??
懶漢式
DCL懶漢式:在懶漢式基礎上加入雙重檢驗鎖,保證線程安全和性能。
?
package com.lyc.single;//懶漢式單例模式public class LazyMan {private LazyMan(){?}private volatile static LazyMan lazyMan;public LazyMan getInstance(){//雙重檢測鎖模式的懶漢式單例,簡稱:DCL懶漢式if (lazyMan==null){synchronized (LazyMan.class){if (lazyMan==null){lazyMan=new LazyMan();//不是一個原子性操作//1.分配內存給這個對象//2.執行構造方法,初始化對象//3.將這個對象指向這個空間//可能會發生指令重排,導致對象還沒初始化完成,就返回了//如果有兩個線程在創建對象,可能會造成對象還沒初始化完成,就返回了//如果在創建對象時,多個線程同時判斷到lazyMan==null,就會創建多個對象//解決方法://1.使用synchronized關鍵字//2.使用volatile關鍵字}}}return lazyMan;}//單線程下是安全的//多線程下是不安全的,需要在加鎖。}?
靜態內部類
?package com.lyc.single;//靜態內部類實現public class Holder {private Holder(){?}public static Holder getInstance(){return ?InnerClass.holder;}public static class InnerClass{private static final Holder holder = new Holder();}}
單例不安全,因為有反射
枚舉
?package com.lyc.single;?import java.lang.reflect.Method;?//enum是什么,枚舉本身也是一個Class類public enum EnumSingle {INSTANCE;?public EnumSingle getInstance() {return INSTANCE;}}?package com.lyc.single;?import java.lang.reflect.Constructor;import java.lang.reflect.Method;?public class SingleTest {public static void main(String[] args) throws Exception{EnumSingle instance = EnumSingle.INSTANCE;Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class, int.class);declaredConstructor.setAccessible(true);EnumSingle instance1 = declaredConstructor.newInstance();System.out.println(instance.hashCode());System.out.println(instance1.hashCode());}}
??