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();
}
}