定义
使一个对象能够被当前范围之外的代码使用
对象逸出
一种错误的发布,当一个对象还没构造完成时就被其他线程所见
安全地发布对象
在静态初始化函数中初始化一个对象引用
将对象的引用保存到volatile类型或者AtomicReference对象中
将对象的引用保存到某个正确构造对象的final类型域中
将对象的引用保存到一个由锁保护的域中
/**
线程不安全
单例实例在第一次使用时创建
懒汉模式
*/
public class StaticDemo {
private StaticDemo() {}
private static StaticDemo instance = null;
public static StaticDemo getInstance() {
if (instance == null) {
instance = new StaticDemo();
}
return instance;
}
}
/**
线程安全
单例实例在第一次使用时创建
懒汉模式
不推荐(性能开销过大)
*/
public class StaticDemo {
private StaticDemo() {}
private static StaticDemo instance = null;
public static synchronized StaticDemo getInstance() {
if (instance == null) {
instance = new StaticDemo();
}
return instance;
}
}
/**
线程不安全
单例实例在第一次使用时创建
更好的懒汉模式(双重同步锁单例模式)
*/
public class StaticDemo {
private StaticDemo() {}
private static StaticDemo instance = null;
public static StaticDemo getInstance() {
if (instance == null) {
// 双重检测机制
synchronized(StaticDemo.class) {// 同步锁
if (instance == null) {
// 1.分配对象内存空间
// 2.初始化对象
// 3.设置instance指向分配的内存
// 多线程情况下,JVM和cpu优化会发生指令重排导致线程不安全,有概率发生空指针异常
// 1.分配对象内存空间
// 3.设置instance指向分配的内存
// 2.初始化对象
instance = new StaticDemo();
}
}
}
return instance;
}
}
/**
线程安全
单例实例在第一次使用时创建
更好的懒汉模式(双重同步锁单例模式,加入volatile,禁止指令重排)
*/
public class StaticDemo {
private StaticDemo() {}
private volatile static StaticDemo instance = null;
public static StaticDemo getInstance() {
if (instance == null) {
// 双重检测机制
synchronized(StaticDemo.class) {// 同步锁
if (instance == null) {
// 1.分配对象内存空间
// 2.初始化对象
// 3.设置instance指向分配的内存
// 多线程情况下,JVM和cpu优化会发生指令重排
// 1.分配对象内存空间
// 3.设置instance指向分配的内存
// 2.初始化对象
instance = new StaticDemo();
}
}
}
return instance;
}
}
/**
线程安全
单例实例在类转载时创建
饿汉模式
使用的注意点:构造函数内不用做太多操作,否则加载时间可能过长;此类被使用,否则会造成资源的浪费
*/
public class StaticDemo {
private StaticDemo() {}
private static StaticDemo instance = new StaticDemo();
public static StaticDemo getInstance() {
return instance;
}
}
/**
线程安全
单例实例在类转载时创建
饿汉模式
使用的注意点:构造函数内不用做太多操作,否则加载时间可能过长;此类被使用,否则会造成资源的浪费
*/
public class StaticDemo {
private StaticDemo() {}
// 静态代码的顺序不一样也可能造成执行结果有差异
private static StaticDemo instance = null;
static {
instance = new StaticDemo();
}
public static StaticDemo getInstance() {
return instance;
}
}
/**
线程安全
安全性和性能相比懒汉模式和饿汉模式更好
枚举模式
推荐使用
*/
public class StaticDemo {
private StaticDemo() {}
public static StaticDemo getInstance() {
return Singleton.INSTANCE.getInstance();
}
private enum Singleton {
INSTANCE;
private StaticDemo singleton;
// JVM保证这个方法只被调用一次
Singleton() {
singleton = new StaticDemo();
}
public StaticDemo getInstance() {
return singleton;
}
}
}