前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java安全的发布对象

Java安全的发布对象

原创
作者头像
开源日记
修改2021-01-21 11:18:19
5630
修改2021-01-21 11:18:19
举报
文章被收录于专栏:JVMGCJVMGC

安全发布对象

  • 在静态初始化函数中初始化一个对象引用
  • 将对象的引用保存到volatile类型域或者AtomicReference对象中
  • 将对象的引用保存到某个正确构造对象的final类型域中
  • 将对象的引用保存到一个由锁保护的域中

Spring 框架中,Spring管理的类都是单例模式。如何保证一个实例只被初始化一次,且线程安全?通过不同单例的写法,具体描述安全发布对象的四种方法:

在静态初始化函数中初始化一个对象的引用(不推荐)

代码语言:txt
复制
package com.rumenz.task.single;


//线程安全
//饿汉模式
//静态代码块初始化
public class SingletonExample {
    private SingletonExample(){
        //初始化操作
    }
    private static SingletonExample singletonExample=null;

    static {
        singletonExample=new SingletonExample();
    }

    public static SingletonExample getInstance(){
        return singletonExample;
    }
}

//或者
package com.rumenz.task.single;
//线程安全
//饿汉模式
//静态代码块初始化
public class SingletonExample {
    private SingletonExample(){

        //初始化操作

    }
    private static SingletonExample singletonExample=new SingletonExample();



    public static SingletonExample getInstance(){
        return singletonExample;
    }
}

缺点:用不用都会初始化对象,如果初始化工作较多,加载速度会变慢,影响系统性能。

将对象的引用保存到volatile类型或AtomicReference对象中(推荐)

代码语言:txt
复制
package com.rumenz.task.single;

//线程安全
//懒汉模式
public class SingletonExample1 {

    private SingletonExample1() {
        //初始化操作
    }
    // 1、memory = allocate() 分配对象的内存空间
    // 2、ctorInstance() 初始化对象
    // 3、instance = memory 设置instance指向刚分配的内存
    // 单例对象 volatile + 双重检测机制 -> 禁止指令重排
    private volatile static SingletonExample1 singletonExample1=null;
    //静态工厂方法
    public static SingletonExample1 getInstance(){
        if(singletonExample1==null){ //双重检测
            synchronized(SingletonExample1.class){ //同步锁
                if(singletonExample1==null){
                    singletonExample1=new SingletonExample1();
                }
            }
        }
        return singletonExample1;
    }
}


//或者

package com.rumenz.task.single;

import java.util.concurrent.atomic.AtomicReference;

class SingletonAtomicReference<T> {
    /**
     * Implement the singleton using an AtomicReference.
     */
    public static AtomicReference<SingletonAtomicReference> sSingletonAR =
            new AtomicReference<>(null);

    /**
     * Define a non-static field.
     */
    private T mField;

    /**
     * * @return The value of the field.
     */
    public T getField() {
        return mField;
    }

    /**
     * Set and return the value of the field.
     */
    public T setField (T f) { return mField = f; }

    /**
     * The static instance() method from the Singleton pattern.
     */
    public static <T> SingletonAtomicReference instance() {
        // Get the current value of the singleton.
        SingletonAtomicReference<T> singleton = sSingletonAR.get();

        // Run this code if the singleton is not yet initialized.
        if (singleton == null) {

            singleton = new SingletonAtomicReference<>();
            //CAS
            if (!sSingletonAR.compareAndSet(null, singleton))
                singleton = sSingletonAR.get();
        }
        // Return the singleton's current value.
        return singleton;
    }
}

class R{
    private Integer age;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public R(Integer age) {
        this.age = age;
    }

    public static void main(String[] args) {
        R o = (R)SingletonAtomicReference.instance().setField(new R(300));

        System.out.println(o.getAge());


    }
}

优点:按需加载 缺点:第一次初始化的时候可能会比较慢

AtomicReference使用场景
代码语言:txt
复制
private static AtomicReference<DBConnector> instance = new AtomicReference<>();

public static DBConnector getDBConnector(DBConfig dBConfig) {
    // First try
    DBConnector con = instance.get();
    if (con == null) {
        con = // ...

        if (instance.compareAndSet(null, con)) {
            // Successful swap, return our copy
            return con;
        } else {
            // Lost the race, poll again
            return instance.get():
        }
    }

    // Already present value
    return con;
}

通过synchronized(不推荐)

代码语言:txt
复制
package com.rumenz.task.single;

public class SingletonExample3 {
    //私有构造函数
    private SingletonExample3(){
        //初始化操作
    }

    private static SingletonExample3 singletonExample3=null;
    //静态的工厂方法
    public static synchronized SingletonExample3 getSingletonExample3(){
         if(singletonExample3==null){
             singletonExample3=new SingletonExample3();
         }
         return singletonExample3;
    }
}

缺点:每次进入getSingletonExample3都会加锁,耗费资源,故不推荐使用。

枚举(推荐)

代码语言:txt
复制
package com.rumenz.task.single;

public class SingletonExample4 {

    //私有构造函数
    private SingletonExample4(){
       //初始化
    }
    public static SingletonExample4 getSingletonExample4(){
        return Singleton.INSTANCE.getSingleton();
    }
    private enum Singleton{
        INSTANCE;
        private SingletonExample4 singleton;
        Singleton(){
            singleton=new SingletonExample4();
        }
        public SingletonExample4 getSingleton(){
            return singleton;
        }

    }
}

优点:天然线程安全,可防止反射生成实例,推荐使用

将对象的引用保存到一个由锁保护的域中

代码语言:txt
复制
public class SingletonExample {
    private static final Map<String, SingletonExample> MAP = new ConcurrentHashMap<>();
 
    private String fileLoc;
     
    private SingletonExample(String fileLoc) {
        this.fileLoc = fileLoc;
    }
 
    public static SingletonExample getSingletonInst(String index, String fileLocation) {
        return MAP.computeIfAbsent(index, k -> new SingletonExample(fileLocation));
    }
}
wx.jpg
wx.jpg

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安全发布对象
    • 在静态初始化函数中初始化一个对象的引用(不推荐)
      • 将对象的引用保存到volatile类型或AtomicReference对象中(推荐)
        • AtomicReference使用场景
      • 通过synchronized(不推荐)
        • 枚举(推荐)
          • 将对象的引用保存到一个由锁保护的域中
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档