单例模式
单例模式三个主要特点:
1、构造方法私有化;
2、实例化的变量引用私有化;
3、获取实例的方法共有。
实现方式
1. 程序启动的时候初始化
1)利用静态变量
public class Singleton {
/*
* 利用静态变量来记录Singleton的唯一实例
* 直接初始化静态变量,这样就可以确保线程安全了
*/
private static Singleton uniqueInstance = new Singleton();
/*
* 构造器私有化,只有Singleton类内才可以调用构造器
*/
private Singleton(){
}
public static Singleton getInstance(){
return uniqueInstance;
}
}
2)通过枚举类实现单例模式(解决了序列化、反射的问题)
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
2.使用的时候初始化
1)DCL(double check lock)
publicclass Singleton {
/**
* 单例对象实例
*/
private volatile static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
volatile关键字必须有,防止指令重排序。
指令重排序导致的问题
2)利用内部类延迟加载
public class LazyInitHolderSingleton {
private LazyInitHolderSingleton() {
}
private static class SingletonHolder {
static final LazyInitHolderSingleton INSTANCE = new LazyInitHolderSingleton();
}
public static LazyInitHolderSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
把Singleton实例放到一个静态内部类中,这样就避免了静态实例在Singleton类加载的时候就创建对象,并且由于静态内部类只会被加载一次.
静态内部类和非静态内部类一样,都不会因为外部内的加载而加载,同时静态内部类的加载不需要依附外部类,在使用时才加载,不过在加载静态内部类的过程中也会加载外部类
https://www.cnblogs.com/zouxiangzhongyan/p/10762540.html
利用枚举实现demo
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();
}
}
public class Test {
public static void main(String [] args){
System.out.println(User.getInstance());
System.out.println(User.getInstance());
System.out.println(User.getInstance()==User.getInstance()); //结果为true
}
}