【问题标题】:Singleton with Enum vs Singleton with double-checked locking带有枚举的单例与带有双重检查锁定的单例
【发布时间】:2012-08-13 05:33:53
【问题描述】:

我想知道在多线程环境中哪个在实践中更好。我将 Singleton 理解为 Enum 类型在加载类时创建一个实例。除此之外,我没有看到任何其他重要的东西。有什么优点和缺点吗?

作为Enum 类型的单例:

 public enum Singleton {
      INSTANCE;
      public void doSomething(){ ... }
 }

单例double-checked locking:

 public class Singleton{
      private volatile static Singleton instance;

      private Singleton(){}
      public static Singleton getInstance(){
           if(instance == null){
                 synchronized(Singleton.class){
                       if(instance == null){
                           instance = new Singleton();
                       }
                 }
           }
           return instance;
      }

 }

【问题讨论】:

  • @DmitryBeransky 这个版本从 1.5 开始是安全的,实际上是 1.4。但即使是 1.6 也面临着生命的终结。 (如果线程安全,我的意思是在确切的代码中是安全的。这是不安全的,因为它很容易出错并且单例很可能是不安全的(当然是不明智的)。)

标签: java multithreading singleton


【解决方案1】:

通常在多线程应用程序中,更简单、更容易理解的代码更容易工作。

在我看来,第一个例子明显比第二个简单,这才是最重要的。

使用enum 的主要优点是它更简单,更复杂的例子是不合理的。双锁定示例允许您以有趣的方式更改单例以进行单元测试,但我相信这给您带来的问题可以通过另一种方式解决。

【讨论】:

    【解决方案2】:

    单例存在更多问题,而不仅仅是正确的实现。

    人们经常使用单例,因此他们不必在应该或必须在多个方法之间传递对象的地方传递对象。

    有很多用 Singleton 实例化 jdbc 连接的例子。

    在您需要此连接的方法中,您可以轻松访问它,因为它是一个 Singleton。

    public enum DBConnection {
      INSTANCE;
      private Connection connection;
      public Connection getConnection(){
        if(connection == null){
          instantiateConnection();
        }
        return connection;
      }
    }
    

    并通过

    访问它
    DBConnection.INSTANCE.getConnection();
    

    但通常最好使用依赖注入和一个令人愉快的框架来做到这一点。以 GUICE 为例。

    在您的代码中,您不会在 DBConnection.INSTANCE 上进行调用,而不是在 getConnection() 上,您的 Class 将有一个使用 @Inject 注释的字段 DBConnection。而你只需使用它。

    @Inject
    private DBConnection dBConnection;
    

    并且该类将被 @Singleton 注释为单例,并且框架将确保它是单例。

    如果你有不同的环境,比如测试和生产,你可以让框架为每个环境注入不同的对象。

    【讨论】:

      【解决方案3】:

      使用enum 创建singleton 因其简单快捷的方式而广受欢迎。

      此外,您在这里与双重检查锁定进行了比较,但还有其他方法,不使用枚举。

      例如:

      public class Test{
      
            private static Test uniqueInstance = new Test();
      
            private Test(){}
      
            public static Test getInstance(){
      
      
                   return uniqueInstance;     
               }
      
       }
      

      但我认为enum 是一种非常直截了当的方法,为singleton 提供了更清晰的自我解释代码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多