疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

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


 

 
废话不多说,直接上代码:
 
[java] view plain copy 在CODE上查看代码片派生到我的代码片
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类的使用。这时可以将上面的代码修改如下:
[java] 
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对象和数据。这就做到了线程内部的数据是共享的,而线程与线程之间的数据是独立的。