发布对象
发布对象:使一个对象能够被当前范围之外的代码所使用;
对象逸出:一种错误的发布,当一个对象还没有构造完成时,就被其他对象所见。
安全发布对象
- 在静态初始化函数中初始化一个对象引用;
- 将对象的引用保存到volatile类型域或者AtomicReference对象中;
- 将对象的引用保存到某个正确构造对象的final类型域中;
- 将对象的引用保存到一个由锁保护的域中;
例子:单例对象例子
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:02
*
* 懒汉模式
* 线程不安全
*/
public class SingletonExample1 {
//私有构造
private SingletonExample1(){
}
//单例对象
private static SingletonExample1 instance = null;
//静态工厂方法
public static SingletonExample1 getInstance(){
if (instance == null){
instance = new SingletonExample1();
}
return instance;
}
}
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:02
*
* 饿汉模式 不足:1、如果构造函数处理过多,会导致类加载过慢;
* 2、对象在类加载的时候初始化完成,没有实际调用的话会造成资源的浪费。
* 线程安全:因为类加载只有一次
*
*/
public class SingletonExample2 {
//私有构造
private SingletonExample2(){
}
//单例对象
private static SingletonExample2 instance = new SingletonExample2();
//静态工厂方法
public static SingletonExample2 getInstance(){
return instance;
}
}
package com.liuhy.test.testapplication.singleton;
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:02
*
* 懒汉模式
* 修改线程安全:
* 1、getInstance方法加synchronized 保证线程安全性,
* 但是会造成性能上的开销,不推荐使用
*/
public class SingletonExample3 {
//私有构造
private SingletonExample3(){
}
//单例对象
private static SingletonExample3 instance = null;
//静态工厂方法
public static synchronized SingletonExample3 getInstance(){
if (instance == null){
instance = new SingletonExample3();
}
return instance;
}
}
package com.liuhy.test.testapplication.singleton;
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:02
* <p>
* 懒汉模式
* 线程不安全:
* 1、synchronized下沉到new对象这步,使用双重检测机制,
* 但是这样线程不安全,因为cpu指令重排的问题.
*
*/
public class SingletonExample4 {
//私有构造
private SingletonExample4() {
}
/**
* 初始化对象步骤
* 1、分配对象内存空间
* 2、初始化对象
* 3、这是instance指向刚分配的内存空间
*
* JVM和CPU优化,发生指令重排
* 1、分配对象内存空间
* 3、这是instance指向刚分配的内存空间
* 2、初始化对象
*
*
*/
//单例对象
private static SingletonExample4 instance = null;
//静态工厂方法
public static SingletonExample4 getInstance() {
if (instance == null) { //双重检测机制
synchronized (SingletonExample4.class) {
if (instance == null) {
instance = new SingletonExample4(); //这样当线程1按重排后执行到3的时候,线程2进来就会返回一个未初始化的对象.
}
}
}
return instance;
}
}
package com.liuhy.test.testapplication.singleton;
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:02
* <p>
* 懒汉模式
* 线程不安全:
* 1、synchronized下沉到new对象这步,使用双重检测机制,
* 但是这样线程不安全,因为cpu指令重排的问题.
* 使用volatile+双重检测机制-->禁止指令重排,保证线程安全
*
*/
public class SingletonExample5 {
//私有构造
private SingletonExample5() {
}
/**
* 初始化对象步骤
* 1、分配对象内存空间
* 2、初始化对象
* 3、这是instance指向刚分配的内存空间
*
* JVM和CPU优化,发生指令重排
* 1、分配对象内存空间
* 3、这是instance指向刚分配的内存空间
* 2、初始化对象
*
*
*/
//单例对象 使用volatile+双重检测机制-->禁止指令重排,从而保证线程安全
private volatile static SingletonExample5 instance = null;
//静态工厂方法
public static SingletonExample5 getInstance() {
if (instance == null) { //双重检测机制
synchronized (SingletonExample5.class) {
if (instance == null) {
instance = new SingletonExample5(); //这样当线程1按重排后执行到3的时候,线程2进来就会返回一个未初始化的对象.
}
}
}
return instance;
}
}
package com.liuhy.test.testapplication.singleton;
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:02
*
* 饿汉模式 不足:1、如果构造函数处理过多,会导致类加载过慢;
* 2、对象在类加载的时候初始化完成,没有实际调用的话会造成资源的浪费。
* 线程安全:因为类加载只有一次
*
*/
public class SingletonExample6 {
//私有构造
private SingletonExample6(){
}
//单例对象
private static SingletonExample6 instance = null;
static {
instance = new SingletonExample6();
}
//静态工厂方法
public static SingletonExample6 getInstance(){
return instance;
}
public static void main(String[] args) {
System.out.println(getInstance());
}
}
枚举模式,比较推荐。线程安全
package com.liuhy.test.testapplication.singleton;
/**
* @Auther: liuhy
* @Date: 2018/11/23 10:57
*
* 枚举模式
* 线程安全
* 比较推荐这种方式:相比懒汉模式线程安全更容易保证,
* 相比饿汉式不会造成资源浪费
*/
public class SingletonExample7 {
private SingletonExample7(){
}
public static SingletonExample7 getInstance(){
return Singleton.SINGLETON.getInstance();
}
//定义一个私有的枚举类
private enum Singleton{
SINGLETON;
private SingletonExample7 singletonExample7;
// JVM保证这个方法绝对只调用一次
Singleton(){
singletonExample7 = new SingletonExample7();
}
public SingletonExample7 getInstance(){
return singletonExample7;
}
}
public static void main(String[] args) {
getInstance();
}
}