发布对象
- 发布对象:使一个对象能够被当前范围之外的代码所使用
package com.alan.concurrency.example.publish;
import com.alan.concurrency.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
/**
* 演示发布对象线程不安全
*/
@Slf4j
@NotThreadSafe
public class UnsafePublish {
private String[] states = {"a","b","c"};
public String[] getStates(){
return states;
}
public static void main(String[] args) {
UnsafePublish unsafePublish = new UnsafePublish();
log.info("{}", Arrays.toString(unsafePublish.getStates()));
unsafePublish.getStates()[0]="d";
log.info("{}", Arrays.toString(unsafePublish.getStates()));
}
}
- 对象逸出:一种错误的发布。当一个对象还没有构造完成时,就使它被其然线程所见。
package com.alan.concurrency.example.publish;
import com.alan.concurrency.annoations.NotRecommend;
import com.alan.concurrency.annoations.NotThreadSafe;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@NotThreadSafe
@NotRecommend
public class Escape {
private int thisCanBeEscape = 0;
//无参构造
public Escape() {
new InnerClass();
}
//定义内部类
private class InnerClass{
//定义无参构造
public InnerClass() {
log.info("{}",Escape.this.thisCanBeEscape);
}
}
public static void main(String[] args) {
new Escape();
}
}
安全发布对象的四种方法
图片.png通过单例模式演示
- 懒汉模式
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.NotThreadSafe;
/**
* 懒汉模式
* 单例实例在第一次使用时进行创建
*/
@NotThreadSafe
public class SingletonExample1 {
//创建私有构造函数
private SingletonExample1(){
}
//创建静态对象
private static SingletonExample1 instance = null;
//静态的工厂方法
public static SingletonExample1 getInstance(){
if(null == instance){
instance = new SingletonExample1();
}
return instance;
}
}
- 饿汉模式
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.NotThreadSafe;
import com.alan.concurrency.annoations.ThreadSafe;
/**
* 饿汉模式
* 单例实例在类装载时进行创建
* 应用场景 1、构造函数加载资源不是很多 2、实例一定会被使用,否则造成资源浪费
*/
@ThreadSafe
public class SingletonExample2 {
//创建私有构造函数
private SingletonExample2(){
}
//创建静态对象
private static SingletonExample2 instance = new SingletonExample2();
//静态的工厂方法
public static SingletonExample2 getInstance(){
return instance;
}
}
- 懒汉模式 使用synchronized线程安全,但是开销过大,不推荐使用
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.NotRecommend;
import com.alan.concurrency.annoations.NotThreadSafe;
import com.alan.concurrency.annoations.ThreadSafe;
/**
* 懒汉模式
* 单例实例在第一次使用时进行创建,使用synchronized关键字
* 开销过大,不推荐使用
*/
@ThreadSafe
@NotRecommend
public class SingletonExample3 {
//创建私有构造函数
private SingletonExample3(){
}
//创建静态对象
private static SingletonExample3 instance = null;
//静态的工厂方法
public static synchronized SingletonExample3 getInstance(){
if(null == instance){
instance = new SingletonExample3();
}
return instance;
}
}
- 懒汉模式 -》双重同步锁单例模式 线程不安全
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.NotRecommend;
import com.alan.concurrency.annoations.NotThreadSafe;
import com.alan.concurrency.annoations.ThreadSafe;
/**
* 懒汉模式 -》双重同步锁单例模式
* 单例实例在第一次使用时进行创建
* 开销过大,不推荐使用
*/
@NotThreadSafe
public class SingletonExample4 {
//创建私有构造函数
private SingletonExample4(){
}
//创建静态对象
private static SingletonExample4 instance = null;
/**
* 创建对象的步骤
* 1、memory = allocate() 分配对象的内存空间
* 2、ctoInstance() 初始化对象
* 3、instance = memory 设置instance指向刚分配的内存
*
* JVM和CPU优化造成了指令重排
* 1、memory = allocate() 分配对象的内存空间
* 3、instance = memory 设置instance指向刚分配的内存
* 2、ctoInstance() 初始化对象
*/
//静态的工厂方法
public static SingletonExample4 getInstance(){
if(null == instance){ //双重检测机制 //B
synchronized (SingletonExample4.class){ //同步锁
if(null == instance){
instance = new SingletonExample4(); //A - 3第三步
}
}
}
return instance;
}
}
- 懒汉模式 -》双重同步锁单例模式 加入volatile修饰
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.NotThreadSafe;
import com.alan.concurrency.annoations.ThreadSafe;
/**
* 懒汉模式 -》双重同步锁单例模式 加入volatile修饰
* 单例实例在第一次使用时进行创建
* 开销过大,不推荐使用
*/
@ThreadSafe
public class SingletonExample5 {
//创建私有构造函数
private SingletonExample5(){
}
//创建静态对象
//通过volatile防止发生指令重排
private volatile static SingletonExample5 instance = null;
/**
* 创建对象的步骤
* 1、memory = allocate() 分配对象的内存空间
* 2、ctoInstance() 初始化对象
* 3、instance = memory 设置instance指向刚分配的内存
*
* JVM和CPU优化造成了指令重排
* 1、memory = allocate() 分配对象的内存空间
* 3、instance = memory 设置instance指向刚分配的内存
* 2、ctoInstance() 初始化对象
*/
//静态的工厂方法
public static SingletonExample5 getInstance(){
if(null == instance){ //双重检测机制 //B
synchronized (SingletonExample5.class){ //同步锁
if(null == instance){
instance = new SingletonExample5(); //A - 3第三步
}
}
}
return instance;
}
}
- 饿汉模式 静态代码块
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.ThreadSafe;
/**
* 饿汉模式
* 单例实例在类装载时进行创建
* 应用场景 1、构造函数加载资源不是很多 2、实例一定会被使用,否则造成资源浪费
*/
@ThreadSafe
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().hashCode());
System.out.println(getInstance().hashCode());
}
}
- 通过枚举实现
package com.alan.concurrency.example.singleton;
import com.alan.concurrency.annoations.Recommend;
import com.alan.concurrency.annoations.ThreadSafe;
/**
* 枚举方式实现 :最安全的
*/
@ThreadSafe
@Recommend
public class SingletonExample7 {
//私有构造函数
private SingletonExample7(){
}
public static SingletonExample7 getInstance(){
return Singleton.INSTANCE.getInstance();
}
//定义枚举类
private enum Singleton {
INSTANCE;
private SingletonExample7 singleton;
//JVM保证这个方法绝对只被调用一次
Singleton(){
singleton = new SingletonExample7();
}
public SingletonExample7 getInstance(){
return singleton;
}
}
}
网友评论