单例模式

128 阅读1分钟

饿汉式

package singleton.hungry;

public class HungrySingleton {

    public static HungrySingleton instance = new HungrySingleton();

}

懒汉式

package singleton.lazy;

public class LazySingleton {

    // volatile避免指令重排,产生线程安全问题
    private volatile static LazySingleton instance;

    private static boolean initialized = false;

    private LazySingleton() {
        // 防止反射破坏单例
        synchronized (LazySingleton.class) {
            if (!initialized) {
                initialized = true;
            } else {
                throw new RuntimeException("单例被破坏!");
            }
        }

    }

    /**
     * 线程不安全
     * @return
     */
    public static LazySingleton getInstance1() {
        if (null == instance) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            instance = new LazySingleton();
        }

        return instance;
    }

    /**
     * 线程安全,加锁存在效率问题
     * @return
     */
    public static synchronized LazySingleton getInstance2() {
        if (null == instance) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            instance = new LazySingleton();
        }

        return instance;
    }

    /**
     * 双重校验锁
     * @return
     */
    public static LazySingleton getInstance3() {
        if (null == instance) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized (LazySingleton.class) {
                if (null == instance) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }

}

静态内部类实现

package singleton.lazy;

public class StaticInnerClassSingleton {

    private StaticInnerClassSingleton() {}

    private static class singletonHolder {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }

    public static StaticInnerClassSingleton getMyInstance() {
        return singletonHolder.INSTANCE;
    }

}

注册登记式

package singleton.register;

import java.util.HashMap;

public class MapRegisterSingleton {

    private static HashMap<String, Object> registerMap = new HashMap();

    private MapRegisterSingleton() {

    }

    public static MapRegisterSingleton getMyInstance(String name) {
        if (null == name) {
            name = MapRegisterSingleton.class.getName();
        }

        if (null == registerMap.get(name)) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            synchronized (MapRegisterSingleton.class) {
                if (null == registerMap.get(name)) {
                    registerMap.put(name, new MapRegisterSingleton());
                }
            }
        }

        return (MapRegisterSingleton) registerMap.get(name);
    }
}

枚举

package singleton.register;

public enum EnumRegisterSingleton {

    INSTANCE;

}

序列化/反序列化

package singleton.serialize;

import java.io.Serializable;

public class SerializeSingleton implements Serializable {

    private static final SerializeSingleton INSTANCE = new SerializeSingleton();

    private SerializeSingleton() {

    }

    public static SerializeSingleton getMyInstance() {
        return INSTANCE;
    }

    /**
     * 保证单例
     * @return
     */
    private Object readResolve() {
        return INSTANCE;
    }
}

测试

package singleton.test;

import singleton.hungry.HungrySingleton;
import singleton.lazy.LazySingleton;
import singleton.lazy.StaticInnerClassSingleton;
import singleton.register.MapRegisterSingleton;
import singleton.serialize.SerializeSingleton;

import java.io.*;
import java.lang.reflect.Constructor;

public class test {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
//            new Thread(() -> testHungrySingleton()).start();
            new Thread(() -> testLazySingleton()).start();
//            new Thread(() -> testStaticInnerClassSingleton()).start();
//            new Thread(() -> testMapRegisterSingleton()).start();
        }
//        testSerializeSingleton();
    }

    public static void testHungrySingleton() {
        System.out.println(HungrySingleton.instance);
    }

    public static void testLazySingleton() {
        System.out.println(LazySingleton.getInstance1());
//        System.out.println(LazySingleton.getInstance2());
//        System.out.println(LazySingleton.getInstance3());

        // 反射破坏单例
//        Class<LazySingleton> clazz = LazySingleton.class;
//        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
//        for (int i = 0; i < constructors.length; i++) {
//            Constructor<?> constructor = constructors[i];
//            constructor.setAccessible(true);
//            try {
//                Object o = constructor.newInstance();
//                System.out.println(o);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
    }

    public static void testStaticInnerClassSingleton() {
        System.out.println(StaticInnerClassSingleton.getMyInstance());
    }

    public static void testMapRegisterSingleton() {
        System.out.println(MapRegisterSingleton.getMyInstance("s"));
    }

    public static void testSerializeSingleton() {
        SerializeSingleton s1;
        SerializeSingleton s2 = SerializeSingleton.getMyInstance();

        try {
            FileOutputStream fos = new FileOutputStream("testSerializeSingleton.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(s2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("testSerializeSingleton.obj");
            ObjectInputStream osi = new ObjectInputStream(fis);
            s1 = (SerializeSingleton) osi.readObject();
            osi.close();

            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s1 == s2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}