设计模式-单例模式

饿汉模式

​ 特点:线程安全,在加载类的时候实例化,因为只加载一次所以只会创建一个实例,但是实例即使不用也会一直保存在内存里,会占用内存。

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉模式(两种模式)

线程不安全的

​ 特点:线程不安全,在需的时候实例化。

​ 分析:因为new是分两步走的,一步是创建内存对象,一步是将引用变量指向内存变量,当并发的时候可能会出现线程A创建了内存a但还没指向内存a,线程B看这个instance还是null就又去创建了一块内存b,然后将instance指向内存b,这样两个线程获取到的实例就不是同一个。

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance() {
    	if (instance == null) {
             instance = new Singleton();
        }
        return instance;
    }
}
线程安全的

​ 特点:线程安全,但是每次使用都会加锁影响性能。

public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static synchronized Singleton getInstance() {
    	if (instance == null) {
             instance = new Singleton();
        }
        return instance;
    }
}

枚举

​ 特点:线程安全、简单、第一次使用加载。

​ 分析:枚举除了不能被继承外几乎可以看成一个类,枚举在被编译后它的实例实际上都是static的,每个实例也只会被初始化一次,这个是由虚拟机保证的。在使用枚举的时候才会加载枚举,这整个过程和用静态内部类实现单例很相似。

public enum Singleton {
	INSTANCE;
    public void doSomeThing() {}
}

双重检查

​ 特点:线程安全,第一次使用加载

​ 分析:没有加volatile的双重检查在 J2SE 1.4 或早期版本在多线程或者 JVM 调优时会无序写入,是不可用的。加入volatile后才可以保证它的有序性。

public class Singleton  {
    private volatile static Singleton instance;
    private Sinleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态内部类

​ 特点:第一次获取的时候初始化实例、代码简洁、线程安全。是比较推荐的模式

​ 分析:是对线程安全的懒汉模式的优化,第一次getInstance()的时候加载SingletonHolder类,然后instance才会被实例化,还是因为类只会加载一次,static代码也只会在类被加载的时候执行一次,所以只有一个instance实例。

public class Singleton {
    private Singleton(){}
    public static class SingletonHolder {
        private static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

容器获取

​ 特点:管理多种类型的单例,通过统一接口获取操作。但是如果key的hash值一样后面的会覆盖前面的。

public class Singleton {
	private static Map<String, Object> objMap = new HashMap<String, Object>;
    private Singleton() {}
    public static void registerService(String key, Object instance) {
        if (!objMap.containsKey(key)) {
            objMap.put(key, instance);
        }
    }
    pulbic static Object getService(String key) {
        return objMap.get(key);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值