在java中注入/访问线程安全单例的最佳方法

时间:2016-02-02 03:37:27

标签: java multithreading singleton

我完全对这段代码感到困惑,因为我知道目的是让线程安全访问对象DataService的单个实例,但我不知道它是否实现了这一点。

它对我来说很突出 来电课程:

protected final DataService dataService = DataService.getInstance();

Singleton类方法:

private static DataService dService=null;
public static synchronized DataService getInstance() {
    if (dService == null)
        dService = new DataService();
    return dService;
}

在调用类中使用受保护的最终修饰符可以实现什么?

这些是必要的还是一种好的做法?

3 个答案:

答案 0 :(得分:1)

第一行的受保护和最终修饰符对您所指的单身性质没有任何贡献。

受保护只是访问修饰符,final决定是否可以重新分配变量。

真正使这个单身人员成为definition of singleton的事实是你只创建了一个dService对象(通过new DataService())并且由于该方法是同步的,所以你可以保证该方法将会不能同时调用,这可能导致错误地创建两个单独的对象。

答案 1 :(得分:1)

正如Brian Benzinger所说,protected和final修饰符对单例类的线程安全性没有贡献。受保护定义了Caller类中字段的可见性,即该字段可以由包中的其他类访问。最终修饰符表示该字段必须在实例化时明确赋值,并且以后不能重新分配。

虽然有很多方法可以在Java中实现单例模式,但这是我所知道的最佳实现:

class Foo {
    private static volatile Bar bar = null;
    public static Bar getBar() {
        if (bar == null) {
            synchronized(Foo.class) {
                if (bar == null)
                    bar = new Bar(); 
            }
        }
        return bar;
    }
}

答案 2 :(得分:0)

所以我最终挖了自己。

我发现这种做单身的方式效率低下,简称为

Double checked locking

“在软件工程中,双重检查锁定(也称为”双重检查锁定优化“)是一种软件设计模式,用于通过首先测试锁定标准来减少获取锁定的开销(”在没有实际获取锁定的情况下锁定提示“”。仅当锁定标准检查指示需要锁定时,实际锁定逻辑才会继续。 “ “ 由于在某些极端情况下同步方法可能会使性能降低100倍或更高 “

java 1.5+中提到的最好方法是使用volatile。

class Foo {
    private volatile Helper helper;
    public Helper getHelper() {
        Helper result = helper;
        if (result == null) {
            synchronized(this) {
                result = helper;
                if (result == null) {
                    helper = result = new Helper();
                }
            }
        }
        return result;
    }

    // other functions and members...
}

“volatile字段只访问一次(由于”返回结果;而不是“返回帮助程序”),这可以将方法的整体性能提高多达25% “