java中单例模式的几种写法
2017-05-14 11:00
489 查看
什么是单例模式
单例模式是使用的最广泛的设计模式之一,用来确保一个类对外只提供唯一的实例,比如连接池、缓存、日志对象的实现基本都用的单例模式。实现单例的方法主要有以下几种,每种都有各自的优缺点,为了实现真正的单例,我们可以根据实际需求,选择合适的方法。1. 饿汉模式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }
优点: 简单,线程安全
缺点: 不能延时加载
推荐指数: 4星
说明: 类初始化时就加载静态变量,创建了实例,不存在多线程问题,缺点是不能在实际使用的时候才创建对象
2. 懒汉模式
线程不安全public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
优点: 延迟加载
缺点:线程不安全
推荐指数: 2星
说明:在多线程环境下,很可能产生多个实例。
线程安全
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
优点: 延迟加载,线程安全
缺点:性能较低
推荐指数: 3星
说明:保证了线程安全,但是由于是直接对方法进行同步,会降低性能,实际上只有在初次调用此方法时,才需要加锁来确保线程安全,一旦设置好instance实例之后,就不需再同步该方法了,也就是说,除了第一次,以后每次调用该方法,同步都是多余的
3. 双重检查锁(DCL)
public class Singleton { private volatile static Singleton instance;//volatile可防止指令重排 private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
优点: 延迟加载,线程安全,性能较高
缺点:较为繁琐,不适用于jdk1.5以下的版本
推荐指数: 4星
说明:该方法是对懒汉模式的改进,既保证了线程安全,又不是对整个方法进行同步,对性能基本没有什么影响。不足之处是需要使用volatile关键字来保证可靠性,只能在jdk1.5及以上的版本使用,因为在jdk1.5以下版本,对于volatile关键字的实现会导致DCL的失效,具体可以参考这篇文章:Java 并发编程:volatile的使用及其原理
4. 枚举
public enum Singleton { INSTANCE; public void doSomething() {} }
优点:代码简洁, 线程安全
缺点:非延迟加载
推荐指数: 5星
说明:通过枚举方式来创建单例是《Effective Java》作者Joshua Bloch大力推荐的,因为它有以下几点优势:
1. 无法通过反射调用创建实例,而在其他类型中,即使是私有方法,也能通过反射,创建新的实例。查看 java.lang.reflect.Constructor的newInstance()方法中有如下代码,说明枚举类型是禁止了通过反射构造枚举对象的
if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException("Cannot reflectively create enum objects");
2.可以有效的防止反序列化,以下是java.lang.Enum类的代码,可以看出,enum类型无法被反序列化
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("can't deserialize enum"); } private void readObjectNoData() throws ObjectStreamException { throw new InvalidObjectException("can't deserialize enum"); }
3 枚举实例无法被克隆,以下是java.lang.Enum代码,如果要强行进行clone,直接抛出异常
protected final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }
5. 静态内部类
public class Singleton{ private Singleton(){} public static Singleton getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder{ private static Singleton INSTANCE = new Singleton(); } }
优点: 线程安全,延迟加载
缺点:
推荐指数: 5星
说明:该方式也称为IoDH( Initialization Demand Holder),可以说是结合了饿汉模式和懒汉模式的优点,既实现了延迟加载,也保证了线程安全,建议优先采用该方式创建单例。
参考:
1. wiki-单例模式
2. 单例模式方法大全
3. 单例模式的七种写法
相关文章推荐
- java设计模式基础-单例模式的几种写法
- Java:单例模式的几种写法
- Java多线程编程-单例模式几种写法的错与对
- Java多线程编程-单例模式几种写法的错与对
- Java多线程编程-单例模式几种写法的错与对
- Java中单例模式的7种写法
- 单例模式java中的几种写法和确保多线程下安全
- Java多线程编程-单例模式几种写法的错与对
- Java多线程编程-(12)-单例模式几种写法的错与对
- Java多线程编程-单例模式几种写法的错与对
- Java中单例模式的七种写法
- 单例模式java中的几种写法和确保多线程下安全
- Java中单例模式的七种写法
- Java多线程编程-单例模式几种写法的错与对
- JAVA中单例模式的几种实现方式
- java设计模式之单例模式(几种写法及比较)
- 单例模式java中的几种写法和确保多线程下安全
- 单例模式java中的几种写法和确保多线程下安全
- Java多线程编程-单例模式几种写法的错与对
- Java多线程编程-单例模式几种写法的错与对