问题代码如下:单例类:
public class WhateverClass{
  private static WhateverClass instance;  private static Object lockObj = new Object();  private HashMap map;  private WhateverClass(){}  public static WhateverClass getInstance() throws Exception{
    if(instance == null){
        synchronized(lockObj){
          if(instance == null){
            instance = new WhateverClass();
            instance.init();
          }
        }
    }
    return instance;
  }  private void init() throws Exception{
    map = new HashMap();
    map.put("xxx", "xxx");
    map.put("xxxx", 1111);
    // ..........
  }  public Something createSomething(){
    // some code like:
    Object o = map.get("xxx");
    // some more code
    return something;
  }
}调用:
Something st = WhateverClass.getInstance().createSomething();

解决方案 »

  1.   

    双重检查锁定啊
    感觉这个程序有问题啊
    synchronized(lockObj)应该是synchronized(WhateverClass.class)吧
      

  2.   

    有问题
    synchronized(lockObj)实现同步时应该用同一个对象上的锁,程序中的lockObj不是同一对象吧!
      

  3.   

    双重检查没有问题,反而是对程序效率的优化。
    synchronized(lockObj)应该是synchronized(WhateverClass.class)确实是这里的问题!
      

  4.   

    看起来好像没什么问题啊,除了一个不必要的lockObj
      

  5.   

    http://www.ibm.com/developerworks/cn/java/j-dcl.html
      

  6.   

    由于 Java 内存模型的限制,双检锁在 JDK 5 之前是无效的,在 JDK 5 及之后需要在静态成员那里加上个 volatile 关键字,否则也不能保证仅产生一个实例。由于双检锁在 Java 中很复杂,因此在 Java 中不建议使用,建议使用强制初始化。对于 Java 双检锁说明最好的一篇文章(署名几乎都是大牛级的人物):
    http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
      

  7.   

    volatile 可以保证线程对于共享变量的可见性,如果不加的话,共享变量被 A 线程修改后,同时进来的 B 线程并不知道这个共享变量已经被修改。
      

  8.   

    其他的没什么问题,但我不知道你这个方法写这里是用来干什么的.   public Something createSomething() {
    // some code like:
    Object o = map.get("xxx");
    // some more code
    return something;
        }
      

  9.   

    你的bug呢!这边的 synchronized(lockObj)感觉应该  synchronized("随便写什么") 这样比较稳定。因为String 是不可修改的。
      

  10.   

    不懂啥是双检锁 不过我刚才去搜索了下 发现了这个 
    http://chaoforever.blog.sohu.com/103394321.htmlLZ是不是担心发生这个情况呢~现在的问题越来越脱离生活了..平时接触不到啊..
      

  11.   

    这个代码只是模拟一下现场,不必考虑逻辑。我碰到的是个简单的错误,在
    Object o = map.get("xxx");
    行抛出nullpointer异常了。
      

  12.   

    ZangXT bao110908 推荐的文章好棒啊,以前从没想到,感激涕零。
    好像最好的办法就是在定义成员的时候直接初始化了。又有一个问题:
    如果构造函数抛出异常了,这个异常是不是无法捕获了?
    例如:
    public class TestInstance {
      public static void main(String[] args) {
        try{
          A.ins.shit();
        }catch(Exception e){
          System.out.println("xxxxxxx");
        }
      }
    }
    class A{
      public static A ins = new A();
      
      private A() {
        throw new RuntimeException("shit");
      }
      
      public void shit(){
        System.out.println("shit");
      }
    }
      

  13.   

    就LZ的例子而言,如果init()不是分配了很多珍贵资源的话,我个人比较喜欢
    private static final WhateverClass instance = new WhateverClass();
    static {
      try {
        instance.init();
      } catch (Exception ex) {
        throw new RuntimeException(ex);
      }
    }
      

  14.   


    支持!你的用法是想一开始就把map给实例并赋值..为什么不用静态块?