2013-03-18 39 views
1

这两个班是一样的吗?是否正在实例化非最终静态变量线程安全?

public class SingleTone { 

    // yes this is a bug what if i change the class this way 
    // private static SingleTone instance = new SingleTone(); 
    // and empty constructor? 
    private static SingleTone instance; 
    private SingleTone() { 
     instance = new SingleTone(); 
    } 

    public static SingleTone getInstance(){ 
     return instance; 
    } 
} 

public class SingleTone { 

    private final static SingleTone instance = new SingleTone(); 

    private SingleTone() { 
    } 

    public static SingleTone getInstance(){ 
     return instance; 
    } 
} 

是在有最终没有任何变化线程安全问题,通过构造函数实例?

问题2:

什么

private final static SingleTone instance = new SingleTone(); 

    private SingleTone() { 
    } 

,这之间的差异:

private final static SingleTone instance; 

    private SingleTone() { 
     instance = new SingleTone(); 
    } 
+0

为了澄清更多:如果我这样重写我的第一个例子私有静态SingleTone实例=新SingleTone();并删除构造函数实例!什么是使用最终的好处! (我正在寻求线程安全问题而不是性能) – 2013-03-18 12:17:08

+1

您问题的原始版本的两个部分都包含错误。而你的“澄清”问题现在如此令人困惑/混乱,以至于无法回避......国际海事组织。 – 2013-03-18 12:18:01

+0

可以回答的一点是:有或没有'最终'字段*有效最终*,因为它被保证只能分配一次。它是线程安全的,因为分配发生在类初始化时。 – 2013-03-18 12:19:55

回答

2

Queston 1个

你的第一个例子不工作。

就好像你拨打这个电话SingleTone.getInstance()该类型已创建的对象的时候,才返回null

第二个例子正常工作

问题2

同样的情况,你就是instatiating一构造函数中的静态字段。这是没有意义的,因为你不能保证在访问静态字段之前调用构造函数。

你可以这样做,而不是:

private final static SingleTone instance; 

static { 
    instance = new SingleTone(); 
} 

这将实例化静态字段第一次加载类时。


回答您的评论。

如果你这样做:

private static final SingleTone instance = new SingleTone(); 

这是线程安全的,就好像第一个线程处理不当完成初始化类,而另一个线程试图访问它的其他线程将被阻塞。

更多信息,请参阅这个问题:Thread safety of static blocks in Java

+0

是的,你是正确的,如果我重写我的第一个例子这样private static SingleTone instance = new SingleTone();并删除构造函数实例!什么是使用最终的好处! (我正在寻求线程安全问题不是性能) – 2013-03-18 12:14:51

+0

更新的答案根据您的评论 – cowls 2013-03-18 12:21:27

+0

谢谢我得到了错误!然而在我的评论中,我没有使用最终变量而不是最终变量。我更新了答案,请再看一遍 – 2013-03-18 12:37:42

0

两个选项实际上都是相同的(但super()呼叫的构造在这两种情况下丢失)。

但是,实现一个singleton是使用私有静态字段的Java往往被弃用。现在,我会使用枚举。

public enum Elvis { 
    INSTANCE; 
    private final String[] favoriteSongs = 
     { "Hound Dog", "Heartbreak Hotel" }; 

    public void printFavorites() { 
     System.out.println(Arrays.toString(favoriteSongs)); 
    } 
} 

如果你想进一步阅读:http://www.drdobbs.com/jvm/creating-and-destroying-java-objects-par/208403883?pgno=3

+0

我不要求执行单音我知道枚举方式。 – 2013-03-18 12:21:18

0

SingleTone类必须返回一个参考,所以第一个例子是完全错误的。

考虑以下过程: 由JVM 开始1.类加载2.类被装入JVM。 3.构造执行 4.对象创建完成

公共类SingleTone { 对于这个例子实例将活1个2 私人最终静态SingleTone实例之间=新SingleTone();

private SingleTone() { 
} 

public static SingleTone getInstance(){ 
    return instance; 
} 

}

公共类SingleTone { 对于这个例子实例将在3和4 私人最终静态SingleTone实例之间活着;

private SingleTone() { 
    instance = new SingleTone(); 
} 

public static SingleTone getInstance(){ 
    return instance; 
} 

}

相关问题