单例模式

ThreadLocalSingleton 线程单例模式

上一节开始也介绍过有关线程内的单例,主要就是利用了线程副本threadlocal来保证线程内单例。因为是线程独享,所以就不会初始化多次了。不多说,上代码。

public class ThreadLocalSingleton {
    // 下面是简化代码 不得不说java8开始代码看起来是舒服了 但是阅读成本就增加了
    //  private static final ThreadLocal<ThreadLocalSingleton> local = ThreadLocal.withInitial(ThreadLocalSingleton::new);

    private static final ThreadLocal<ThreadLocalSingleton> local = new ThreadLocal<ThreadLocalSingleton>() {
        @Override
        protected ThreadLocalSingleton initialValue() {
            return new ThreadLocalSingleton();
        }
    };

    private ThreadLocalSingleton() {
    }

    public static ThreadLocalSingleton getInstance() {
        return local.get();
    }
}

容器式单例模式

spring中就利用了容器模式来管理bean,主要是通过创建一个map对象来存储class名称和对应的实例化对象的。

public class ContainerSingleton {
	//创建map来存储数据,起名ioc主要是让大家联想到spring的ioc
    private static final Map<String, Object> ioc = new ConcurrentHashMap<>();
    private ContainerSingleton() {
    }
    public static Object getInstance(String className) {
    	//这个位置是一定要增加锁的
    	//有人会问到,我不是已经使用ConcurrentHashMap了吗,为什么还要加锁呢
    	//这是因为有人把ConcurrentHashMap的线程安全和单例搞混了
    	//在ConcurrentHashMap中put和set等方法是线程安全的,也就是说在操作map中数据的时候可以保证线程安全
    	//但是并不是说我们的getInstance就是线程安全的了,是我们本身的代码存在问题
    	//假如说我们写的单例只有这些代码的话ConcurrentHashMap是可以换成HashMap的
        synchronized (ioc) {
            if (!ioc.containsKey(className)) {
                Object object = null;
                try {
                    object = Class.forName(className).newInstance();
                    //将实例化的对象放入ioc中
                    ioc.put(className, object);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return object;
            }
            return ioc.get(className);
        }
    }
}

枚举式单例

听名字就知道我们使用枚举类来创建单例,单例存在着一些天然的优势,在java的实现机制上,enum属性值本身就为单例,并且底层对序列化和反射破坏单例的问题进行了相关优化,当然缺点就是稍微占用了些资源。


public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}

这个可能稍微难理解了些,给大家写个例子

public class User {
    private User(){}
    static enum SingletonEnum{
        INSTANCE;
        private User user;
        private SingletonEnum(){
            user=new User();
        }
        public User getInstnce(){
            return user;
        }
    }
    public static final User getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}

破坏单例模式的情况

反射破坏单例

还在整理

序列化破坏单例

还在整理

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐