简体   繁体   English

线程安全单例和内部类解决方案

[英]Thread safe singleton and inner class solution

This is how I always created a thread-safe singleton, in order to use it in a multi-threading app. 这就是我始终创建线程安全单例的方式,以便在多线程应用程序中使用它。

public class Logger {

    private Logger() {}

    private static Logger instance = new Logger();

    public static Logger getInstance() {
        return instance;
    }

    public void log(String s) {
        // Log here
    }
}

Today I was studying to take my Java certification and on the book I found this other solution: 今天,我正在学习获得Java认证,并且在书上找到了另一个解决方案:

public class Logger {

    private Logger() {}

    private static Logger instance;

    private static class LoggerHolder {
        public static Logger logger = new Logger();
    }

    public static Logger getInstance() {
        return LoggerHolder.logger;
    }

    public void log(String s) {
        // Log here
    }
}

They don't mention about the other one. 他们没有提到另一个。

What's better? 有什么更好的? And what's the difference between the two solution? 两种解决方案之间有什么区别?

The second example is less likely to create an instance just because you accessed the class. 第二个示例不太可能仅仅因为您访问了类而创建了实例。 Instead you would have to access the inner class. 相反,您将必须访问内部类。 This level of paranoia makes sense for the JDK Library designers but in a more controlled code base, it is over the top IMHO. 对于JDK库设计人员而言,这种偏执感是有意义的,但是在受更多控制的代码库中,它是最重要的恕我直言。

I prefer simplicity and would use this instead 我更喜欢简单,会用它代替

public enum MyLogger {
    INSTANCE;

    public void log(String s) {
       // log here
    }
}

I recommend strongly against creating a class called Logger There is already enough confusion over the many implementations of this class available including one builtin. 我强烈建议不要创建一个称为Logger类。对于此类的许多实现,包括一个内置的实现,已经有足够的困惑。

The second one is lazy. 第二个是懒惰的。 If, by some miracle, the program loads the class but never calls getInstance() , the logger instance, which might be an expensive object to create, won't be created. 如果程序奇迹getInstance()加载了该类但从未调用过getInstance() ,则将不会创建可能是创建昂贵对象的记录器实例。

Frankly, if a singleton is really needed (and with dependency injection frameworks, they're almost always unneeded), I prefer the first solution, which is easier to understand. 坦白说,如果确实需要单例(并且使用依赖注入框架,几乎总是不需要它们),我更喜欢第一种解决方案,它更易于理解。 I've rarely, if ever, seen a singleton whose class was loaded but which was never used in real code. 我很少(如果曾经见过)看到一个加载了类但从未在实际代码中使用过的单例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM