单例模式
- 目标:保证一个类只有一个实例
- 实现:
- 不可被外部创建
- 限制内部访问方式
- 内部保证实例唯一
单例模式——饿汉式
package zhang.task;
/**
* 饿汉式——创建类的同时创建实例
*/
public class SingletonHungry {
//初始化实例instance
private static final SingletonHungry instance = new SingletonHungry();
//用private限制构造器,使实例不能在类外部被创建
private SingletonHungry(){
}
//开放访问,使外部能通过getInstance()方法获得实例instance
public static SingletonHungry getInstance(){
return instance;
}
}
- 实现:在创建类的同时创建唯一实例instance,通过private限制构造器避免类在外部被实例化,通过开放getInstance()方法访问唯一实例
- 特点:饿汉式会提前进行实例化,没有延迟加载,不管是否使用都会有一个已经初始化的实例在内存中
单例模式——懒汉式
package zhang.task;
/**
* 懒汉式——需要时创建单例
*/
public class SingletonLazy {
private static SingletonLazy instance;
//用private限制构造器,使实例不能在类外部被创建
private SingletonLazy(){
}
//需要实例时,执行判断,若实例为空,则创建实例,若实例已存在,则直接返回实例;
public static SingletonLazy getInstance(){
if(instance==null){
instance = new SingletonLazy();
}
return instance;
}
}
- 实现:实现了延迟加载,在需要的时候创建实例
- 特点:可能出现线程不安全情况,在线程并发的情况下存在创建多个实例的情况
单例模式——DCL
package zhang.task;
/**
* DCL式——懒汉式进阶双重检查锁版本,实现线程安全
*/
public class SingletonDoubleChecking {
private static SingletonDoubleChecking instance;
//用private限制构造器,使实例不能在类外部被创建
private SingletonDoubleChecking(){
}
public static SingletonDoubleChecking getInstance(){
//检查是否为空,不为空时不检查,节省性能消耗;为空时可能有并发问题
if(instance==null){
//同步代码块,保证不会被并发获取
synchronized (SingletonDoubleChecking.class){
if(instance==null){
//进入时再次判断,若不为空则不建实例,保证单例
instance = new SingletonDoubleChecking();
}
}
}
return instance;
}
}
- 实现:需要实例的时候进行判断,不为空时直接调用实例,为空时进入排队队列,再次判断,若为空创建实例,不为空则返回已存在实例;
- 特点:需要时创建实例,通过synchronized实现线程安全问题
单例模式——枚举
package zhang.task;
/**
* 枚举式单例,枚举的创建由JVM保证,因此不会出现并发问题,构造器自动私有,外部不能创建,只能引用
* 用法为:SingletonEnum.INSTANCE.doSomething();
*/
public enum SingletonEnum {
//唯一实例,默认未public static final
INSTANCE;
public String name;
public void doSomething(){
System.out.println("doSomething");
}
public static void main(String[] args){
SingletonEnum.INSTANCE.doSomething();
}
}
- 实现:使用枚举类型创建实例,在枚举中明确了构造方法限制为私有,在访问枚举实例时会执行构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次。在调用构造方法时,我们的单例被实例化。
- 特点:枚举类型的单例保证不会出现并发问题