標籤:object file util 過程 執行個體 建立 put color spring源碼
單例模式是一種建立性模式,是一種建立對象的方式,主要指的就是一個類在整個程式的啟動並執行過程中對象只會建立一個執行個體,就是只會被new一次,然後下次訪問這個對象的時候是不用重新建立對象的。官方的解釋是:保證一個類僅有一個執行個體,並提供一個訪問它的全域訪問點。單例模式有很多種寫法,比如:懶漢式(安全執行緒/線程不安全)、餓漢式、枚舉式、序列化式、內部類式、註冊式、註冊登記式、雙重檢查鎖(DCL)等等。
下面使用窮舉法舉幾個例子:
1.spring源碼中的單例,可以使用getBean返回不同的對象。
2.咱們程式裡面多線程同時操作一個txt檔案時會出現錯誤,這個檔案的建立可能是一個單例。
3.還有比如太陽、月亮、人等等應該也是可以說成是單例的,因為對象只有一個,所有人看到的是同一個太陽、月亮。
4.還有日常生活中的日曆。
餓漢式
package pattern.single;public class Hungry { private Hungry(){ } private static final Hungry hungry=new Hungry(); public static Hungry getInstance(){ return hungry; }}
package pattern.single;public class SingleTest { public static void main(String[] args) { Hungry hungry=Hungry.getInstance(); Hungry hungry1=Hungry.getInstance(); System.out.println(hungry==hungry1); }}
餓漢式的優點是效能比較高,沒有現成安全問題,還是對象在初始化的時候就已經建立,不管會不會用到都得建立,所以會有浪費資源。
懶漢式線程不安全
package pattern.single;public class LazyOne { private LazyOne(){} private static LazyOne lazy=null; public static LazyOne getInstance(){ if(lazy==null){ lazy=new LazyOne(); } return lazy; }}
package pattern.single;public class SingleTest { public static void main(String[] args) { LazyOne lazyOne=LazyOne.getInstance(); System.out.println(lazyOne); }}
這種方法只能在單線程的環境下使用,在多線程情況下存線上程安全問題,但是只會在用到的時候建立對象。
懶漢式安全執行緒
package pattern.single;public class LazyTwo { private LazyTwo(){} private static LazyTwo lazy=null; public static synchronized LazyTwo getInstance(){ if(lazy==null){ lazy=new LazyTwo(); } return lazy; }}
package pattern.single;public class SingleTest { public static void main(String[] args) { LazyTwo lazyTwo=LazyTwo.getInstance(); System.out.println(lazyTwo); }}登記式\靜態內部類
package pattern.single;public class LazyThree { private static boolean initialized=false; public LazyThree(){ synchronized (LazyThree.class){ if(initialized==false){ initialized=!initialized; }else{ throw new RuntimeException("單例被攻擊"); } } } public static final LazyThree getInstance(){ return LazyHolder.Lazy; } private static class LazyHolder{ private final static LazyThree Lazy=new LazyThree(); }}
package pattern.single;public class SingleTest { public static void main(String[] args) { LazyThree lazyThree=LazyThree.getInstance(); System.out.println(lazyThree); }}
這種方式的效率比懶漢式安全執行緒的模式更高,同時在初始化的時候也不會載入,避免了資源的浪費。
枚舉式
package pattern.single;public enum RegisterEnum { BLOCK(){ private int r=0; private int g=0; private int b=0; },RED(){ private int r=255; private int g=0; private int b=0; };}
package pattern.single;public class SingleTest { public static void main(String[] args) { RegisterEnum registerEnum=RegisterEnum.BLOCK; System.out.println(registerEnum); }}序列化式
package pattern.single;import java.io.Serializable;public class Seriable implements Serializable { public final static Seriable INSTANCE=new Seriable(); private Seriable(){} public static Seriable getInstance(){ return INSTANCE; } private Object readObject(){ return INSTANCE; }}
package pattern.single;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class SingleTest { public static void main(String[] args) { Seriable s1 = null; Seriable s2 = Seriable.getInstance(); FileOutputStream fos = null; try { fos = new FileOutputStream("obj"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(s2); oos.flush(); oos.close(); FileInputStream fis = new FileInputStream("obj"); ObjectInputStream ois = new ObjectInputStream(fis); s1 = (Seriable)ois.readObject(); ois.close(); System.out.println(s1); System.out.println(s2); System.out.println(s1 == s2); } catch (Exception e) { e.printStackTrace(); } }}註冊式
package pattern.single;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;public class BeanFactory { private BeanFactory(){} private static Map<String,Object> ioc=new ConcurrentHashMap<>(); public static Object getBean(String className) throws Exception { if(ioc.containsKey(className)){ return ioc.get(className); }else{ ioc.put(className,Class.forName(className).newInstance()); } return ioc.get(className); }}
package pattern.single;public class SingleTest { public static void main(String[] args) { Object obj=BeanFactory.getBean("xxx.yyy");
System.out.println(obj);
}
}雙重檢查鎖(DCL)
package pattern.single;public class Singleton { private volatile static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ synchronized (Singleton.class){ if(singleton==null){ singleton=new Singleton(); } } } return singleton; }}
package pattern.single;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class SingleTest { public static void main(String[] args) { Object obj=Singleton.getInstance(); System.out.println(obj); }}
這種方式採用雙鎖機制,安全且在多線程情況下能保持高效能。
單例模式