1. 懶漢模式(double check), 線程安全, 效率不高, 能夠延遲加載java
public class Singleton1 implements Serializable { // 用volatile修飾instance, 禁止指令重排序, 爲保證多線程安全 private volatile static Singleton1 instance = null; private Singleton1() { // 防止反射調用私有構造方法(跳過安全檢查), 重複實例化實例 if (instance != null) { throw new RuntimeException("error:instance=" + instance); } } public static Singleton1 getInstance() { if (instance == null) { synchronized (Singleton1.class) { if (instance == null) { instance = new Singleton1(); } } } return instance; } private Object readResolve() { return instance; // 防止反序列化重複實例化實例 } }
2. 餓漢模式, 線程安全, 效率高, 可是不能延遲加載web
public class Singleton2 implements Serializable { private static Singleton2 instance = new Singleton2(); private Singleton2() { // 防止反射調用私有構造方法(跳過安全檢查),重複實例化實例 if (instance != null) { throw new RuntimeException("error:instance isn't null " + instance); } } public static Singleton2 getInstance() { return instance; } private Object readResolve() { return instance; // 防止反序列化重複實例化實例 } }
3. 私有靜態內部類, 線程安全, 調用效率高, 能夠延遲加載安全
public class Singleton3 { private Singleton3() { } private static class Singleton0 { private static final Singleton3 instance = new Singleton3(); } /* * 獲取私有靜態內部類中的實例對象 */ public static Singleton3 getInstance() { return Singleton0.instance; } }
3種方式的性能分析:多線程
public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); int countNum = 1000; final CountDownLatch count = new CountDownLatch(countNum); for (int i = 0; i < countNum; i++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 1000000; i++) { // Singleton1.getInstance(); // 懶漢模式(double check) // Singleton2.getInstance(); //餓漢模式 Singleton3.getInstance(); // 私有靜態內部類 } count.countDown(); } }).start(); } count.await(); long end = System.currentTimeMillis(); System.out.println(end - start); }
Console輸出:ide
懶漢模式(double check): 310ms性能
餓漢模式: 150msspa
私有靜態內部類: 160ms線程