单例和公共静态变量 Java

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13724230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:47:38  来源:igfitidea点击:

singleton and public static variable Java

javasingletonstatic-variables

提问by Achow

I have 2 options:

我有两个选择:

  1. Singleton Pattern

    class Singleton{
        private static Singleton singleton = null;
    
        public static synchronized Singleton getInstance(){
            if(singleton  == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
  2. using a static finalfield

    private static final Singleton singleton = new Singleton();
    
    public static Singleton getSingleton() {
        return singleton;
    }
    
  1. 单例模式

    class Singleton{
        private static Singleton singleton = null;
    
        public static synchronized Singleton getInstance(){
            if(singleton  == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
  2. 使用static final字段

    private static final Singleton singleton = new Singleton();
    
    public static Singleton getSingleton() {
        return singleton;
    }
    

Whats the difference? (singlethreaded or multithreaded)

有什么不同?(单线程或多线程)

Updates: I am aware of Bill Pugh or enummethod. I am not looking for the correct way, but I have only used 1. Is there really any difference b/w 1 or 2?

更新:我知道 Bill Pugh 或enum方法。我不是在寻找正确的方法,但我只使用了 1。b/w 1 或 2 真的有什么区别吗?

采纳答案by assylias

The main difference is that with the first option , the singleton will only be initialised when getInstanceis called, whereas with the second option, it will get initialized as soon as the containing class is loaded.

主要区别在于,对于第一个选项,单例只会在getInstance被调用时初始化,而对于第二个选项,它会在包含类加载后立即初始化。

A third (preferred) option which is lazy and thread safe is to use an enum:

惰性且线程安全的第三个(首选)选项是使用枚举:

public enum Singleton {
    INSTANCE;
}

回答by Aviram Segal

There is one difference:

有一个区别:

Solution 1 is a lazy initialization, the singleton instance will be created on the first invoke of getInstance

解决方案 1 是延迟初始化,单例实例将在第一次调用时创建 getInstance

Solution 2 is a eager initialization, the singleton instance will be create when the class loades

方案二是eager初始化,类加载时会创建单例

They both are thread safe, calling the second one multi threaded is a little misleading

它们都是线程安全的,调用第二个多线程有点误导

回答by irreputable

The 1st solutions appears to be lazier, but actually not.

第一种解决方案似乎更懒惰,但实际上并非如此。

A class is initialized when a static method/field is accessed for the 1st time.

第一次访问静态方法/字段时初始化类。

It's likely that getInstance()is the only publicly accessible static method/field of the class. That's the point of singleton.

这很可能getInstance()是该类中唯一可公开访问的静态方法/字段。这就是单例的意义所在。

Then the class is initialized when someone calls getInstance()for the 1st time. That means the two solutions are essentially the same in laziness.

然后当有人getInstance()第一次调用时初始化该类。这意味着这两种解决方案在惰性方面基本相同。

Of course, the 2nd solutions looks better and performs better.

当然,第二个解决方案看起来更好,性能更好。

回答by John B

So, with the update both options above are thread-safe. However the synchronizedoption requires each thread that calls instanceto acquire this lock thereby reducing performance if this is done a lot. Also, using synchronizedat the method level has the potential issue of using a publicly available lock (the class itself) that therefore if some thread acquires this lock (which it could) you could end up with deadlock. The static finaloption is more performant but does not do lazy initialization of the singleton (which might not be an issue depending on the system).

因此,通过更新,上述两个选项都是线程安全的。然而,该synchronized选项要求调用instance获取此锁的每个线程如果这样做会降低性能。此外,synchronized在方法级别使用具有使用公开可用锁(类本身)的潜在问题,因此如果某些线程获取此锁(它可能),您可能会以死锁告终。该static final选项的性能更高,但不会对单例进行延迟初始化(这可能不是问题,具体取决于系统)。

Another option that allows thread-safe lazy init of the Singleton is as follows:

另一个允许单例线程安全延迟初始化的选项如下:

 public class MySingleton{
      private static class Builder{
          private static final MySingleton instance = new MySingleton();
      }

      public static MySingleton instance(){
           return Builder.intance;
      }
 }

This works because the static inner class is guarenteed to be initialized before any method in the containing class is executed.

这是有效的,因为在执行包含类中的任何方法之前,保证静态内部类被初始化。

回答by Costi Ciudatu

Singleton implementation in Java (if you really want that) can be performed in a more elegant way than you described for both eager and lazy initialization. Check the enum waydescribed by Joshua Bloch and the SingletonHolder solutionproposed by Bill Pugh respectively.

Java 中的单例实现(如果你真的想要的话)可以以比你描述的急切初始化和延迟初始化更优雅的方式执行。分别检查Joshua Bloch 描述的 enum 方式和Bill Pugh 提出的 SingletonHolder 解决方案

The wikipedia article is also a good start for understanding the pattern and does answer your question.

维基百科文章也是理解模式的良好开端,并且确实回答了您的问题。