public class EagerSingleton { // jvm保證在任何線程訪問uniqueInstance靜態變量以前必定先建立了此實例 public static EagerSingleton uniqueInstance = new EagerSingleton(); // 私有的默認構造子,保證外界沒法直接實例化 private EagerSingleton() { } }
public class EagerSingleton { // jvm保證在任何線程訪問uniqueInstance靜態變量以前必定先建立了此實例 private static EagerSingleton uniqueInstance = new EagerSingleton(); // 私有的默認構造子,保證外界沒法直接實例化 private EagerSingleton() { } // 提供全局訪問點獲取惟一的實例 public static EagerSingleton getInstance() { return uniqueInstance; } }
//懶漢式 同步一個方法可能形成程序執行效率降低100倍,徹底沒有必要每次調用getInstance都加鎖,事實上咱們只想保證一次初始化成功,其他的快速返回而已,若是在getInstance頻繁使用的地方就要考慮從新優化了. public class LazySingleton { private static LazySingleton uniqueInstance; private LazySingleton() { } public static synchronized LazySingleton getInstance() { if (uniqueInstance == null) uniqueInstance = new LazySingleton(); return uniqueInstance; } }
3)"雙檢鎖"(Double-Checked Lock)儘可能將"加鎖"推遲,只在須要時"加鎖"(僅適用於Java 5.0 以上版本,volatile保證原子操做)
happens-before:"什麼什麼必定在什麼什麼以前運行",也就是保證順序性.
如今的CPU有亂序執行的能力(也就是指令會亂序或並行運行,能夠不按咱們寫代碼的順序執行內存的存取過程),而且多個CPU之間的緩存也不保證明時同步,只有上面的happens-before所規定的狀況下才保證順序性.java
JVM可以根據CPU的特性(CPU的多級緩存系統、多核處理器等)適當的從新排序機器指令,使機器指令更符合CPU的執行特色,最大限度的發揮機器的性能.緩存
若是沒有volatile修飾符則可能出現一個線程t1的B操做和另外一線程t2的C操做之間對instance的讀寫沒有happens-before,可能會形成的現象是t1的B操做尚未徹底構形成功,但t2的C已經看到instance爲非空,這樣t2就直接返回了未徹底構造的instance的引用,t2想對instance進行操做就會出問題.app
volatile 的功能:
1. 避免編譯器將變量緩存在寄存器裏
2. 避免編譯器調整代碼執行的順序jvm
優化器在用到這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。性能
public class DoubleCheckedLockingSingleton { // java中使用雙重檢查鎖定機制,因爲Java編譯器和JIT的優化的緣由系統沒法保證咱們指望的執行次序。 // 在java5.0修改了內存模型,使用volatile聲明的變量能夠強制屏蔽編譯器和JIT的優化工做 private volatile static DoubleCheckedLockingSingleton uniqueInstance; private DoubleCheckedLockingSingleton() { } public static DoubleCheckedLockingSingleton getInstance() { if (uniqueInstance == null) { synchronized (DoubleCheckedLockingSingleton.class) { if (uniqueInstance == null) { uniqueInstance = new DoubleCheckedLockingSingleton(); } } } return uniqueInstance; } }
public class LazyInitHolderSingleton { private LazyInitHolderSingleton() { } private static class SingletonHolder { private static final LazyInitHolderSingleton INSTANCE = new LazyInitHolderSingleton(); } public static LazyInitHolderSingleton getInstance() { return SingletonHolder.INSTANCE; } }
public enum SingletonClass { INSTANCE; private String name; public void test() { System.out.println("The Test!"); } public void setName(String name){ this.name= name; } public String getName(){ return name; } } public class TestMain { public static void main(String[] args) { SingletonClass one = SingletonClass.INSTANCE; SingletonClass two = SingletonClass.INSTANCE; one.test(); one.setName("I am a SingletonClass Instance"); System.out.println(one.getName()); if (one == two) { System.out.println("There are same"); } } }
package com.effective.singleton; public class Elvis { private static boolean flag = false; private Elvis(){ } private static class SingletonHolder{ private static final Elvis INSTANCE = new Elvis(); } public static Elvis getInstance() { return SingletonHolder.INSTANCE; } public void doSomethingElse() { } }
package com.effective.singleton; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class ElvisReflectAttack { public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Class<?> classType = Elvis.class; Constructor<?> c = classType.getDeclaredConstructor(null); c.setAccessible(true); Elvis e1 = (Elvis)c.newInstance(); Elvis e2 = Elvis.getInstance(); System.out.println(e1==e2); } }
package com.serialize; import java.io.Serializable; public class SerSingleton implements Serializable { private static final long serialVersionUID = 1L; String name; private SerSingleton() { System.out.println("Singleton is create"); name="SerSingleton"; } private static SerSingleton instance = new SerSingleton(); public static SerSingleton getInstance() { return instance; } public static void createString() { System.out.println("createString in Singleton"); } } @Test public void test() throws IOException, ClassNotFoundException { SerSingleton s1= null; SerSingleton s = SerSingleton.getInstance(); FileOutputStream fos = new FileOutputStream("SerSingleton.obj"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(s); oos.flush(); oos.close(); FileInputStream fis = new FileInputStream("SerSingleton.obj"); ObjectInputStream ois = new ObjectInputStream(fis); s1 = (SerSingleton)ois.readObject(); System.out.println(s==s1); }
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Elvis { private static boolean flag = false; private Elvis() { synchronized (Elvis.class) { System.out.println(" try to instance"); if (flag == false) { System.out.println("first time instance"); flag = !flag; } else { throw new RuntimeException("單例模式被侵犯!"); } } } private static class SingletonHolder { // jvm保證在任何線程訪問INSTANCE靜態變量以前必定先建立了此實例 private static final Elvis INSTANCE = new Elvis(); } public static Elvis getInstance() { System.out.println("in getInstance"); return SingletonHolder.INSTANCE; } public void doSomethingElse() { } public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Class<?> classType = Elvis.class; Constructor<?> c = classType.getDeclaredConstructor(null); c.setAccessible(true); Elvis e1 = (Elvis) c.newInstance(); Elvis e2 = Elvis.getInstance(); System.out.println(e1 == e2); } }
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class SerSingleton implements Serializable { private static final long serialVersionUID = 1L; String name; private SerSingleton() { System.out.println("Singleton is create"); name = "SerSingleton"; } private static SerSingleton instance = new SerSingleton(); public static SerSingleton getInstance() { return instance; } public static void createString() { System.out.println("createString in Singleton"); } private Object readResolve(){ return instance; } public static void main(String[] args) throws IOException, ClassNotFoundException { SerSingleton s1 = null; SerSingleton s = SerSingleton.getInstance(); FileOutputStream fos = null; ObjectOutputStream oos = null; FileInputStream fis = null; ObjectInputStream ois = null; try { fos = new FileOutputStream("SerSingleton.obj"); oos = new ObjectOutputStream(fos); oos.writeObject(s); } finally { oos.flush(); oos.close(); fos.close(); } try{ fis = new FileInputStream("SerSingleton.obj"); ois = new ObjectInputStream(fis); s1 = (SerSingleton) ois.readObject(); }finally{ ois.close(); fis.close(); } System.out.println(s == s1); } }
public enum SingletonClass implements Serializable { INSTANCE; private static final long serialVersionUID = 1L; private String name; public void test() { System.out.println("The Test!"); } public void setName(String name) { this.name = name; } public String getName() { return name; } public static void main(String[] args) throws IOException, ClassNotFoundException { SingletonClass s1 = null; SingletonClass s = SingletonClass.INSTANCE; FileOutputStream fos = null; ObjectOutputStream oos = null; FileInputStream fis = null; ObjectInputStream ois = null; try { fos = new FileOutputStream("SingletonClass.obj"); oos = new ObjectOutputStream(fos); oos.writeObject(s); } finally { oos.flush(); oos.close(); fos.close(); } try { fis = new FileInputStream("SingletonClass.obj"); ois = new ObjectInputStream(fis); s1 = (SingletonClass) ois.readObject(); } finally { ois.close(); fis.close(); } System.out.println(s == s1); } }