1. 单例模式(Singleton)

2022-05-09 21:03:56 浏览数 (1)


1. 单例模式(Singleton)

单例简单的说明

一个类只能有一个实例,该类能自己创建这个实例,并且对外提供获取该实例的接口

单例用在哪?

有时候我们只需要一个类就可以完成所需要的业务了,那么就不需要多次创建对象、管理对象,因为这是一件十分耗费系统资源的事

2. 单例的多种写法

参考上面简单说明把编写分三步:

  • 构造函数私有化
  • 在类的内部创建唯一实例
  • 提供获取实例的接口

2.1 饿汉式,线程安全

代码语言:javascript复制
public class HungrySingleton {

	//构造函数私有化
	private HungrySingleton(){}
	
	//内部创建实例
	private static HungrySingleton hs = new HungrySingleton();
	
	//获取实例的接口
	public static HungrySingleton getInstance(){
		return hs;
	}
}
  • 可能饿了,类加载时该内部实例就已经被创建了,如果没有调用会浪费资源

2.2 懒汉式,线程安全

代码语言:javascript复制
public class LazySingleton {

	//构造函数私有化
	private LazySingleton(){}
	
	//内部先不创建,等到调用接口才创建
	private static LazySingleton ls = null;
	
	//获取实例的接口,同步方法,防止多线程访问创建多个对象
	public static synchronized LazySingleton getInstance(){
		
		if(ls == null){
			ls = new LazySingleton();
		}
		
		return ls;
	}
}
  • 与饿汉式不同,等到调用接口才创建实例

2.3 DCL双重校验锁,线程安全

代码语言:javascript复制
public class DCL {
	
    //构造函数私有化
	private DCL(){}
	
	//可见性
	private volatile static DCL dcl = null;
	
    //获取实例的接口
	public static DCL getInstance(){
		
		if (dcl == null){
			
			//缩小锁的范围,因为是静态方法,用类锁
			synchronized(DCL.class){
				
				if (dcl == null){
					dcl = new DCL();
				}
			}
		}
		return dcl;	
	}
}

2.4 静态内部类,线程安全

代码语言:javascript复制
public class Singleton {
    
    //构造函数私有化
    private Singleton (){}  
    
    //静态内部类
    private static class SingletonHolder {
        
        //final对象不可变
    	private static final Singleton INSTANCE = new Singleton();  
    }  
    
    //获取对象接口
    public static final Singleton getInstance() {  
    	return SingletonHolder.INSTANCE;  
    }  
}
  • 利用类的加载机制,在调用静态内部类的静态变量时才加载内部类,实现延迟加载

2.5 枚举,线程安全

代码语言:javascript复制
public class User {
    //私有化构造函数
    private User(){ }
 
    //定义一个静态枚举类
    static enum SingletonEnum{
        //创建一个枚举对象,该对象天生为单例
        INSTANCE;
        private User user;
        //私有化枚举的构造函数
        private SingletonEnum(){
            user=new User();
        }
        public User getInstnce(){
            return user;
        }
    }
 
    //对外暴露一个获取User对象的静态方法
    public static User getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}

0 人点赞