设计模式系列-单例模式(Singleton)

定义

在一个JVM实例内存中有且只有一个类的实例。

实现方式

基于类的实现

public final class ClassSingleton {
 
    private static ClassSingleton INSTANCE;
    private String info = "Initial info class";
     
    private ClassSingleton() {        
    }
     
    public static ClassSingleton getInstance() {
        if(INSTANCE == null) {
            INSTANCE = new ClassSingleton();
        }
         
        return INSTANCE;
    }
 
    // getters and setters
}

这是比较常见的一种实现方式,但是此方式在多线程调用下会有问题,假如两个线程同时执行 getInstance()方法中
if(INSTANCE == null) ,两个线程各自获得类ClassSingleton不同的实例。为了解决并发创建多实例问题,我们需要在 getInstance() 方法上加锁,实现如下:

public static synchronized ClassSingleton getInstance(){}

直接在方法上加锁,多线程调用会降低性能,是否可以把加锁的代码范围缩小呢?可以双检查机制实现,

public final class ClassSingleton {
 
    private static volatile ClassSingleton INSTANCE;
    private String info = "Initial info class";
     
    private ClassSingleton() {        
    }
     
    public static ClassSingleton getInstance() {
        if(INSTANCE == null) {
        	synchronized(ClassSingleton.class){
        		if(INSTANCE == null) {
					INSTANCE = new ClassSingleton();
				}
        	} 
        } 
        return INSTANCE;
    }
 
    // getters and setters
}

上面代码需要添加 volatile 保证线程安全性,为何要加,请见The “Double-Checked Locking is Broken” Declaration

如何在不加锁的情况下,实现方法的线程安全性呢? 看下下面的一种实现方法:

public final class ClassSingleton {

    private static ClassSingleton INSTANCE = new ClassSingleton();
    private String info = "Initial info class";
     
    private ClassSingleton() {        
    }
     
    public static ClassSingleton getInstance() {
        return INSTANCE;
    }
 
    // getters and setters
}

此方式利用了java 语言规范:类静态字段和块的初始化保障线程安全性 Java Language Specification 12.4.2

上面实现方式我们一般称为:饿汉式,那如何利用此语言特性实现延迟初始化实例?

public final class ClassSingleton {

	private static class ClassSingletonHolder{
		private static final ClassSingleton INSTANCE = new ClassSingleton();
	}
	
    private ClassSingleton() {        
    }
     
    public static ClassSingleton getInstance() {
        return ClassSingletonHolder.INSTANCE;
    }
 
    // getters and setters
}

基于枚举的单例

public enum EnumSingleton {
     
    INSTANCE("Initial class info"); 
  
    private String info;
  
    private EnumSingleton(String info) {
        this.info = info;
    }
  
    public EnumSingleton getInstance() {
        return INSTANCE;
    }
     
    // getters and setters
}

利用 Enum 特性,实现的单例可以保证线程安全,并可以被安全的序列化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值