单例模式在多线程中的使用情况

废话不多说,直接上代码:

class MyThreadScopeData{
    
    private MyThreadScopeData(){}
    private static MyThreadScopeData instance;
    //单例设计模式
    public static MyThreadScopeData getInstance(){
        if(instance ==null){
            instance = new MyThreadScopeData();
        }
        return instance;
    }

}

上述代码中,如果直接用于多线程中是存在问题的,比如线程A调用MyThreadScopeData.getInstance()获取MyThreadScopeData对象,执行到 instance = new MyThreadScopeData();还没返回的时候恰好这时候线程B也来调用MyThreadScopeData.getInstance(),执行了 instance = new MyThreadScopeData();这时候则线程B创建的对象会覆盖线程A创建的对象。所以在线程A中的MyThreadScopeData对象其实已经发生了变化,在实际操作过程中会存在问题。如何避免这种情况呢,就要用到线程中的共享变量问题了,这就要涉及到对ThreadLocal类的使用。这时可以将上面的代码修改如下:

class MyThreadScopeData{
    
    private MyThreadScopeData(){}
    //单例设计模式
    //定义ThreadLocal
    private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
    public static MyThreadScopeData getThreadInstance(){
        MyThreadScopeData instance = map.get();
        if(instance ==null){
            instance = new MyThreadScopeData();
            map.set(instance);
        }
        return instance;
    }
}

在单例类中定义一个ThreadLocal对象用于存储这个类本身的对象,当线程A调用MyThreadScopeData getThreadInstance()方法获取MyThreadScopeData对象的时候,首先从ThreadLocal中获取保存在线程A中的MyThreadScopeData对象,如果没有,则创建一个新的MyThreadScopeData对象,将此对象保存在ThreadLocal对象中,然后返回MyThreadScopeData 对象;当线程B调用MyThreadScopeData getThreadInstance()方法获取MyThreadScopeData 对象的时候,流程和线程A调用MyThreadScopeData getThreadInstance()方法一样。此时线程A和线程B各自保存和操作自己线程范围内的MyThreadScopeData对象和数据。这就做到了线程内部的数据是共享的,而线程与线程之间的数据是独立的。

 

上一篇:《蹲坑也能进大厂》多线程系列-ThreadLocal精讲(基础+源码)


下一篇:保姆级教学,22张图揭开ThreadLocal