Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中实现单例模式的有效方法是什么?_Java_Singleton_Design Patterns - Fatal编程技术网

在Java中实现单例模式的有效方法是什么?

在Java中实现单例模式的有效方法是什么?,java,singleton,design-patterns,Java,Singleton,Design Patterns,在Java中实现单例模式的有效方法是什么?确保您确实需要它。在谷歌上搜索“singleton anti pattern”,查看一些反对它的论点 我认为它本身并没有什么问题,但它只是一种公开某些全局资源/数据的机制,所以请确保这是最好的方法。特别是,我发现(DI)更有用,尤其是在您也使用单元测试的情况下,因为DI允许您使用模拟资源进行测试。Wikipedia有一些单例,也有Java。java 5实现看起来相当完整,而且是线程安全的(双检查锁定应用)。如果你用Java搜索singletons,你很容

在Java中实现单例模式的有效方法是什么?

确保您确实需要它。在谷歌上搜索“singleton anti pattern”,查看一些反对它的论点


我认为它本身并没有什么问题,但它只是一种公开某些全局资源/数据的机制,所以请确保这是最好的方法。特别是,我发现(DI)更有用,尤其是在您也使用单元测试的情况下,因为DI允许您使用模拟资源进行测试。

Wikipedia有一些单例,也有Java。java 5实现看起来相当完整,而且是线程安全的(双检查锁定应用)。如果你用Java搜索singletons,你很容易就会被关于使用它们的类似宗教的争论所绊倒

就我个人而言,我尽量避免单身,原因有很多,其中大部分都可以通过谷歌搜索单身人士找到。我觉得单身人士经常被虐待,因为他们很容易被每个人理解。它们被用作将“全局”数据引入OO设计的机制,之所以使用它们,是因为它很容易绕过对象生命周期管理(或者真正考虑如何从B内部执行a)。看看国际奥委会(IoC)或国际奥委会(DI)之类的东西,寻找一个好的中间立场

如果你真的需要一个,那么维基百科有一个很好的例子,说明了一个单例的正确实现。

忘记;问题太大了。这是最简单的解决方案:

public class A {    

    private static final A INSTANCE = new A();

    private A() {}

    public static A getInstance() {
        return INSTANCE;
    }
}

如果您不需要延迟加载,只需尝试:

public class Singleton {
    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() { return Singleton.INSTANCE; }

    protected Object clone() {
        throw new CloneNotSupportedException();
    }
}
如果希望延迟加载并且希望单例线程安全,请尝试双重检查模式:

public class Singleton {
    private static Singleton instance = null;

    private Singleton() {}

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

    protected Object clone() {
        throw new CloneNotSupportedException();
    }
}

由于双重检查模式不能保证工作(由于编译器的一些问题,我对此一无所知),您也可以尝试同步整个getInstance方法或为所有单例创建注册表。

Java 5+中的线程安全:

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;
    }
}

请注意此处的
volatile
修饰符。:)这一点很重要,因为没有它,JMM(Java内存模型)无法保证其他线程看到其值的变化。同步并没有考虑到这一点——它只是序列化对该代码块的访问

@Bno的回答详细说明了Bill Pugh(FindBugs)推荐的方法,可以说更好。阅读并投票支持他的答案。

使用枚举:

public enum Foo {
    INSTANCE;
}
public enum Foo {
   INSTANCE;
}
Joshua Bloch在谷歌I/O 2008的演讲中解释了这一方法:。另请参见其演示文稿的幻灯片30-32():

实现可序列化单例的正确方法 编辑:安说:

“此方法在功能上等同于公共字段方法,只是它更简洁,免费提供序列化机制,并提供铁一般的保证,即使面对复杂的序列化或反射攻击,也可以防止多次实例化。虽然这种方法尚未被广泛采用,单元素枚举类型是实现单元素枚举的最佳方式


我对一些答案感到困惑,这些答案建议(DI)作为使用单例的替代方案;这些是不相关的概念。您可以使用DI注入单例或非单例(例如,每个线程)实例。至少如果您使用Spring 2.x,这是真的,我不能为其他DI框架说话

因此,我对OP的回答是(除了最简单的示例代码外),如下所示:

  • 使用DI框架,如
  • 使其成为DI配置的一部分,无论依赖项是单例、请求范围、会话范围还是其他类型
  • 这种方法为您提供了一个很好的解耦(因此是灵活且可测试的)体系结构,其中是否使用单例是一个容易逆转的实现细节(当然,前提是您使用的任何单例都是线程安全的)。

    在Java 5.0及更高版本中有效。但我更愿意不使用它,因为我认为它容易出错

    很容易忘记volatile语句,也很难理解为什么需要volatile语句。没有volatile语句,由于双重检查锁定反模式,这段代码将不再是线程安全的。有关这一点,请参阅的第16.2.4段。简言之:此模式(Java 5.0之前或没有volatile语句)可能返回对(仍然)处于错误状态的条形图对象的引用

    这种模式是为性能优化而发明的。但这已经不再是一个真正的问题了。下面的惰性初始化代码速度快,更重要的是,更易于阅读

    class Bar {
        private static class BarHolder {
            public static Bar bar = new Bar();
        }
    
        public static Bar getBar() {
            return BarHolder.bar;
        }
    }
    

    根据用法,有几个“正确”答案

    自Java 5以来,最好的方法是使用枚举:

    public enum Foo {
        INSTANCE;
    }
    
    public enum Foo {
       INSTANCE;
    }
    
    在Java 5之前,最简单的情况是:

    public final class Foo {
    
        private static final Foo INSTANCE = new Foo();
    
        private Foo() {
            if (INSTANCE != null) {
                throw new IllegalStateException("Already instantiated");
            }
        }
    
        public static Foo getInstance() {
            return INSTANCE;
        }
    
        public Object clone() throws CloneNotSupportedException{
            throw new CloneNotSupportedException("Cannot clone instance of this class");
        }
    }
    
    让我们看一下代码。首先,您希望类是final。在本例中,我使用了
    final
    关键字让用户知道它是final。然后您需要将构造函数设置为私有,以防止用户创建自己的Foo。从构造函数引发异常可防止用户使用反射创建第二个Foo。然后创建一个
    private static final Foo
    字段来保存唯一的实例,并创建一个
    public static Foo getInstance()
    方法来返回它。Java规范确保仅在首次使用类时调用构造函数

    当您有一个非常大的对象或大量的构造代码,并且在需要实例之前可能会使用其他可访问的静态方法或字段时,那么并且只有这样,您才需要使用延迟初始化

    您可以使用
    私有静态类
    加载实例。然后,代码如下所示:

    public final class Foo {
    
        private static class FooLoader {
            private static final Foo INSTANCE = new Foo();
        }
    
        private Foo() {
            if (FooLoader.INSTANCE != null) {
                throw new IllegalStateException("Already instantiated");
            }
        }
    
        public static Foo getInstance() {
            return FooLoader.INSTANCE;
        }
    }
    
    由于行
    private static final Foo INSTANCE=new Foo();
    仅在实际使用类傻瓜加载程序时执行,因此这将处理惰性实例
    public class Singleton {
    
        private static Singleton instance = null;
    
        static {
              instance = new Singleton();
              // do some of your instantiation stuff here
        }
    
        private Singleton() {
              if(instance!=null) {
                      throw new ErrorYouWant("Singleton double-instantiation, should never happen!");
              }
        }
    
        public static getSingleton() {
              return instance;
        }
    
    }
    
    public static final INSTANCE == ....
    private Object readResolve() {
      return INSTANCE; // Original singleton instance.
    } 
    
    /**
    * Singleton pattern example using a Java Enum
    */
    public enum Singleton {
        INSTANCE;
        public void execute (String arg) {
            // Perform operation here
        }
    }
    
     // readResolve to prevent another instance of Singleton
     private Object readResolve(){
         return INSTANCE;
     }
    
     /**
     * Singleton pattern example using Java Enum
     */
     public enum EasySingleton {
         INSTANCE;
     }
    
     /**
     * Singleton pattern example with Double checked Locking
     */
     public class DoubleCheckedLockingSingleton {
          private static volatile DoubleCheckedLockingSingleton INSTANCE;
    
          private DoubleCheckedLockingSingleton() {}
    
          public static DoubleCheckedLockingSingleton getInstance() {
              if(INSTANCE == null) {
                 synchronized(DoubleCheckedLockingSingleton.class) {
                     // Double checking Singleton instance
                     if(INSTANCE == null) {
                         INSTANCE = new DoubleCheckedLockingSingleton();
                     }
                 }
              }
              return INSTANCE;
          }
     }
    
     /**
     * Singleton pattern example with static factory method
     */
    
     public class Singleton {
         // Initialized during class loading
         private static final Singleton INSTANCE = new Singleton();
    
         // To prevent creating another instance of 'Singleton'
         private Singleton() {}
    
         public static Singleton getSingleton() {
             return INSTANCE;
         }
     }
    
    public class Foo {
    
        // It will be our sole hero
        private static final Foo INSTANCE = new Foo();
    
        private Foo() {
            if (INSTANCE != null) {
                // SHOUT
                throw new IllegalStateException("Already instantiated");
            }
        }
    
        public static Foo getInstance() {
            return INSTANCE;
        }
    }
    
    class Foo {
    
        // Our now_null_but_going_to_be sole hero
        private static Foo INSTANCE = null;
    
        private Foo() {
            if (INSTANCE != null) {
                // SHOUT
                throw new IllegalStateException("Already instantiated");
            }
        }
    
        public static Foo getInstance() {
            // Creating only  when required.
            if (INSTANCE == null) {
                INSTANCE = new Foo();
            }
            return INSTANCE;
        }
    }
    
    class Foo {
    
        private static Foo INSTANCE = null;
    
        // TODO Add private shouting constructor
    
        public static Foo getInstance() {
            // No more tension of threads
            synchronized (Foo.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Foo();
                }
            }
            return INSTANCE;
        }
    }
    
    class Foo {
    
        // Pay attention to volatile
        private static volatile Foo INSTANCE = null;
    
        // TODO Add private shouting constructor
    
        public static Foo getInstance() {
            if (INSTANCE == null) { // Check 1
                synchronized (Foo.class) {
                    if (INSTANCE == null) { // Check 2
                        INSTANCE = new Foo();
                    }
                }
            }
            return INSTANCE;
        }
    }
    
    class Foo implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private static volatile Foo INSTANCE = null;
    
        // The rest of the things are same as above
    
        // No more fear of serialization
        @SuppressWarnings("unused")
        private Object readResolve() {
            return INSTANCE;
        }
    }
    
    public final class Foo implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        // Wrapped in a inner static class so that loaded only when required
        private static class FooLoader {
    
            // And no more fear of threads
            private static final Foo INSTANCE = new Foo();
        }
    
        // TODO add private shouting construcor
    
        public static Foo getInstance() {
            return FooLoader.INSTANCE;
        }
    
        // Damn you serialization
        @SuppressWarnings("unused")
        private Foo readResolve() {
            return FooLoader.INSTANCE;
        }
    }
    
    public enum Foo {
        INSTANCE;
    }
    
    public class Foo {
    
        // It will be our sole hero
        private static final Foo INSTANCE = new Foo();
    }
    
    public class Singleton {
      private static Singleton singleInstance = new Singleton();
      private Singleton() {}
      public static Singleton getSingleInstance() {
        return singleInstance;
      }
    }
    
    public class Singleton {
    
        private static final Singleton INSTANCE = new Singleton();
    
        private Singleton() {
            if (INSTANCE != null)
                throw new IllegalStateException(“Already instantiated...”);
            }
    
    
        public synchronized static Singleton getInstance() {
            return INSTANCE;
        }
    
    }
    
    public enum Singleton {
        INSTANCE;
    }
    
    public class MySingleton {
        private static MySingleton instance = null;
        private MySingleton() {}
        public static synchronized MySingleton getInstance() {
            if(instance == null) {
                instance = new MySingleton();
            }
            return instance;
        }
    }
    
    public class MySingleton {
        private MySingleton() {}
        private static class MySingletonHolder {
            public final static MySingleton instance = new MySingleton();
        }
        public static MySingleton getInstance() {
            return MySingletonHolder.instance;
        }
    }
    
    public enum SingletonEnum {
      INSTANCE;
      public void doSomething(){
        System.out.println("This is a singleton");
      }
    }
    
    public class Singleton {
    
      private static volatile Singleton instance = null;
    
      private Singleton() {
      }
    
      public static Singleton getInstance() {
        if (instance == null) {
          synchronized (Singleton.class){
            if (instance == null) {
              instance = new Singleton();
            }
          }
        }
        return instance;
      }
    }
    
    public class Singleton {
    
      private static final Singleton instance = new Singleton();
    
      private Singleton() {
      }
    
      public static Singleton getInstance() {
        return instance;
      }
    
      public void doSomething(){
        System.out.println("This is a singleton");
      }
    
    }
    
    public class Singleton {
        // It must be static and final to prevent later modification
        private static final Singleton INSTANCE = new Singleton();
        /** The constructor must be private to prevent external instantiation */
        private Singleton(){}
        /** The public static method allowing to get the instance */
        public static Singleton getInstance() {
            return INSTANCE;
        }
    }
    
    public class Singleton {
        // The constructor must be private to prevent external instantiation
        private Singleton(){}
        /** The public static method allowing to get the instance */
        public static Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
        /**
         * The static inner class responsible for creating your instance only on demand,
         * because the static fields of a class are only initialized when the class
         * is explicitly called and a class initialization is synchronized such that only
         * one thread can perform it, this rule is also applicable to inner static class
         * So here INSTANCE will be created only when SingletonHolder.INSTANCE
         * will be called
         */
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
    }
    
    public class SingletonImpl {
    
        private static SingletonImpl instance;
    
        public static SingletonImpl getInstance() {
            if (instance == null) {
                instance = new SingletonImpl();
            }
            return instance;
        }
    
        public static void setInstance(SingletonImpl impl) {
            instance = impl;
        }
    
        public void a() {
            System.out.println("Default Method");
        }
    }
    
    public class SingletonMock extends SingletonImpl {
    
        @Override
        public void a() {
            System.out.println("Mock Method");
        }
    
    }
    
    public class SingletonImpl {
    
        private static final SingletonImpl instance = new SingletonImpl();
    
        private static SingletonImpl alt;
    
        public static void setInstance(SingletonImpl inst) {
            alt = inst;
        }
    
        public static SingletonImpl getInstance() {
            if (alt != null) {
                return alt;
            }
            return instance;
        }
    
        public void a() {
            System.out.println("Default Method");
        }
    }
    
    public class SingletonMock extends SingletonImpl {
    
        @Override
        public void a() {
            System.out.println("Mock Method");
        }
    
    }
    
     public class Test {
         private static final Test test = new Test();
    
         private Test() {
         }
    
         public static Test getTest() {
             return test;
         }
     }
    
     public class Test {
          private static volatile Test test;
    
          private Test() {
          }
    
          public static Test getTest() {
             if(test == null) {
                 synchronized(Test.class) {
                     if(test == null) {
                         test = new Test();
                     }
                 }
             }
             return test;
         }
     }
    
     public class Test {
    
         private Test() {
         }
    
         private static class TestHolder {
             private static final Test test = new Test();
         }
    
         public static Test getInstance() {
             return TestHolder.test;
         }
     }
    
     public enum MySingleton {
         INSTANCE;
    
         private MySingleton() {
             System.out.println("Here");
         }
     }
    
    public class MySingleton {
    
         private static MySingleton INSTANCE;
    
         public static MySingleton getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new MySingleton();
            }
            return INSTANCE;
        }
        ...
    }
    
    private static MySingleton INSTANCE;
    
    public static synchronized MySingleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new MySingleton();
        }
        return INSTANCE;
    }
    
    private static MySingleton INSTANCE;
    
    public static MySingleton getInstance() {
        if (INSTANCE == null) {
            synchronize(MySingleton.class) {
                INSTANCE = new MySingleton();
            }
        }
        return INSTANCE;
    }
    
    private static MySingleton INSTANCE;
    
    public static MySingleton getInstance() {
        if (INSTANCE == null) {
            synchronized(MySingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = createInstance();
                }
            }
        }
        return INSTANCE;
    }
    
    private static volatile MySingleton INSTANCE;
    
    public static MySingleton getInstance() {
        if (INSTANCE == null) {
            synchronized(MySingleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = createInstance();
                }
            }
        }
        return INSTANCE;
    }
    
    private static volatile MySingleton INSTANCE;
    
    public static MySingleton getInstance() {
        MySingleton result = INSTANCE;
        if (result == null) {
            synchronized(MySingleton.class) {
                result = INSTANCE;
                if (result == null) {
                    INSTANCE = result = createInstance();
                }
            }
        }
        return result;
    }
    
    public class Singleton<T> implements Supplier<T> {
    
        private boolean initialized;
        private Supplier<T> singletonSupplier;
    
        public Singleton(T singletonValue) {
            this.singletonSupplier = () -> singletonValue;
        }
    
        public Singleton(Supplier<T> supplier) {
            this.singletonSupplier = () -> {
                // The initial supplier is temporary; it will be replaced after initialization
                synchronized (supplier) {
                    if (!initialized) {
                        T singletonValue = supplier.get();
                        // Now that the singleton value has been initialized,
                        // replace the blocking supplier with a non-blocking supplier
                        singletonSupplier = () -> singletonValue;
                        initialized = true;
                    }
                    return singletonSupplier.get();
                }
            };
        }
    
        @Override
        public T get() {
            return singletonSupplier.get();
        }
    }