发布对象
- 发布对象 :使一个对象能够被当前范围之外的代码所使用
- 对象溢出: 一种错误的发布。当一个对象还没有构造完成时,就使它被其他线程所见(类的非私有方法返回对象的引用、通过公有静态变量发布对象)
安全发布对象
在对象初始化函数中初始化一个对象引用
将对象的引用保存到volatile类型域或者AtomicReference对象中
将对象的应用保存到某个正确构造对象的final类型域中
-
将对象的引用保存到一个由锁保护的域中
1.懒汉模式 线程不安全
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.NotThreadSafe;
/**
* 单例
* 懒汉模式
* 单例的实例在第一次运行的时候进行创建
* 单线程下安全 ,多线程下不安全
*/
@NotThreadSafe
public class SingletonExample1 {
/**
* 私有构造函数
*/
private SingletonExample1(){
}
/**
* 单例对象
*/
public static SingletonExample1 instance= null;
/**
* 静态的工厂方法
* @return
*/
public static SingletonExample1 getInstance(){
if(instance==null){
instance = new SingletonExample1();
}
return instance;
}
}
2.饿模式 线程安全
单例的实例在类装载的时候进行创建
饿汉模式可能会导致线程资源的浪费
使用的时候注意的问题:
1.私有构造函数在实现的时候没有太多的处理,不然会导致该类加载过慢,出现性能问题
2.在使用过程中存在实际调用,不然会导致资源浪费
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 单例
* 饿汉模式
* 单例的实例在类装载的时候进行创建
* 饿汉模式可能会导致线程资源的浪费
* 使用的时候注意的问题:
* 1.私有构造函数在实现的时候没有太多的处理,不然会导致该类加载过慢,出现性能问题
* 2.在使用过程中存在实际调用,不然会导致资源浪费
*/
@ThreadSafe
public class SingletonExample2 {
/**
* 私有构造函数
*/
private SingletonExample2(){
}
/**
* 单例对象
*/
public static SingletonExample2 instance= new SingletonExample2();
/**
* 静态的工厂方法
* @return
*/
public static SingletonExample2 getInstance(){
return instance;
}
}
3.懒汉模式 引入静态方法锁 线程安全
单例的实例在第一次运行的时候进行创建
不推荐,因为直接引入对象锁导致效率低
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.NotRecommend;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 单例
* 懒汉模式
* 单例的实例在第一次运行的时候进行创建
*/
@ThreadSafe
@NotRecommend
public class SingletonExample3 {
/**
* 私有构造函数
*/
private SingletonExample3(){
}
/**
* 单例对象
*/
public static SingletonExample3 instance= null;
/**
* 静态的工厂方法
* @return
*/
public static synchronized SingletonExample3 getInstance(){
if(instance==null){
instance = new SingletonExample3();
}
return instance;
}
}
4.懒汉模式 线程不安全
主要原因是JVM和CPU优化,发生了指令重排
懒汉模式 -》 双重同步锁单例模式
单例的实例在第一次运行的时候进行创建
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.NotThreadSafe;
/**
* 单例
* 懒汉模式 -》 双重同步锁单例模式
* 单例的实例在第一次运行的时候进行创建
*/
@NotThreadSafe
public class SingletonExample4 {
/**
* 私有构造函数
*/
private SingletonExample4(){
}
//1.memory = allocate() 分配对象的内存空间
//2.ctorInstance() 初始化对象
//3.instance = memory 设置instance 指向刚分配的内存
//jvm 和cpu优化,发生了指令重排
//1.memory = allocate() 分配对象的内存空间
//3.instance = memory 设置instance 指向刚分配的内存
//2.ctorInstance() 初始化对象
/**
* 单例对象
*/
public static SingletonExample4 instance= null;
/**
* 静态的工厂方法
* @return
*/
public static SingletonExample4 getInstance(){
//双重检测机制
if(instance==null){
//同步锁
synchronized (SingletonExample4.class){
if(instance == null){
instance = new SingletonExample4();
}
}
}
return instance;
}
}
5.懒汉模式 引入volatile+双重检测机制禁止指令重拍使线程安全
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 单例
* 懒汉模式 -》 双重同步锁单例模式
* 单例的实例在第一次运行的时候进行创建
*/
@ThreadSafe
public class SingletonExample5 {
/**
* 私有构造函数
*/
private SingletonExample5(){
}
//1.memory = allocate() 分配对象的内存空间
//2.ctorInstance() 初始化对象
//3.instance = memory 设置instance 指向刚分配的内存
/**
* 单例对象 volatile + 双重检测机制 -> 禁止指令重拍
*/
public volatile static SingletonExample5 instance= null;
/**
* 静态的工厂方法
* @return
*/
public static SingletonExample5 getInstance(){
//双重检测机制
if(instance==null){
//同步锁
synchronized (SingletonExample5.class){
if(instance == null){
instance = new SingletonExample5();
}
}
}
return instance;
}
}
6.饿汉模式 线程安全
静态代码块
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 单例
* 饿汉模式
* 单例的实例在类装载的时候进行创建
* 饿汉模式可能会导致线程资源的浪费
* 使用的时候注意的问题:
* 1.私有构造函数在实现的时候没有太多的处理,不然会导致该类加载过慢,出现性能问题
* 2.在使用过程中存在实际调用,不然会导致资源浪费
*/
@ThreadSafe
public class SingletonExample6 {
/**
* 私有构造函数
*/
private SingletonExample6(){
}
/**
* 单例对象
*/
public static SingletonExample6 instance= null;
static {
instance = new SingletonExample6();
}
/**
* 静态的工厂方法
* @return
*/
public static SingletonExample6 getInstance(){
return instance;
}
public static void main(String[] args) {
System.out.println(getInstance().hashCode());
System.out.println(getInstance().hashCode());
}
}
7.枚举模式 线程安全 (最安全)
推荐使用
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.Recommend;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 单例
* 枚举模式
* 最安全
*/
@ThreadSafe
@Recommend
public class SingletonExample7 {
/**
* 私有构造方法
*/
private SingletonExample7 (){
}
public static SingletonExample7 getInstance(){
return Singleton.SINGLETON.getInstance();
}
/**
* 枚举类定义单利实现
*/
private enum Singleton{
/**
* 枚举单例
*/
SINGLETON;
private SingletonExample7 singleton;
/**
* JVM保证这个方法绝对只被调用一次
*/
Singleton(){
singleton = new SingletonExample7();
}
public SingletonExample7 getInstance(){
return singleton;
}
}
}