单例模式
饿汉式
构造器私有化
类的内部创建对象
向外暴露一个静态的公共方法
//饿汉式 静态变量
class Singleton {
//
private Singleton() {
}
private final static Singleton intance = new Singleton();
public static Singleton getIntance() {
return intance;
}
}
可以用 可能造成内存浪费
//饿汉式 静态代码块
class Singleton {
//构造器私有化
private Singleton() {
}
private static Singleton intance;
static {
intance = new Singleton();
}
public static Singleton getIntance() {
return intance;
}
}
懒汉式
//懒汉式 非线程安全的
class Singleton {
private static Singleton instance;
private Singleton(){}
//当使用到该方法时 才去创建instance
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种模式线程不安去
//懒汉式 线程安全 同步方法
class Singleton {
private static Singleton instance;
private Singleton(){}
//当使用到该方法时 才去创建instance
//加入同步处理代码 解决线程安全问题
// 每次掉用都同步 效率太低
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种模式线程安全 但是每次获取实例都线程同步 效率低
/**
* 双重检查
*/
class Singleton {
private static volatile Singleton singleton;
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
双重检查 保证线程安全
会经过三步操作
1.分配内存空间
2.执行构造方法,初始化对象
3.把这个对象指向这个空间
以上的步骤,默认情况是 123 但是,如果出现 132 的情况,恰巧此时A线程占有了,如果此时B线程也要使用的话, 就会直接认为singleton不为空,则会返回singleton,然而此时singleton还没有完成创建, 此时是一片虚无,会导致错误。所以需要在singleton前面加 volatile 。
/**
* 静态内部类 推荐使用
*/
class Singleton {
private static volatile Singleton singleton;
//根据jvm类装载机制来保证初始化
private static class SingletonIntstance{
private static final Singleton INSTANCE = new Singleton();
}
public static synchronized Singleton getInstance() {
return SingletonIntstance.INSTANCE;
}
}
public class SingletonTest07 {
}
//枚举
enum Singleton {
INSTANCE;
}