Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.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 - Fatal编程技术网

用Java编写单例的不同方法

用Java编写单例的不同方法,java,singleton,Java,Singleton,用java编写单例的经典做法如下: public class SingletonObject { private SingletonObject() { } public static SingletonObject getSingletonObject() { if (ref == null) // it's ok, we can call this constructor ref = new Sin

用java编写单例的经典做法如下:

public class SingletonObject
{
    private SingletonObject()
    {
    }

    public static SingletonObject getSingletonObject()
    {
      if (ref == null)
          // it's ok, we can call this constructor
          ref = new SingletonObject();
      return ref;
    }

    private static SingletonObject ref;
}
如果需要在多线程情况下运行synchronized关键字,我们可以添加它

但我更喜欢这样写:

public class SingletonObject
{
    private SingletonObject()
    {
        // no code req'd
    }

    public static SingletonObject getSingletonObject()
    {
      return ref;
    }

    private static SingletonObject ref = new SingletonObject();
}

我认为这更简洁,但奇怪的是,我没有看到任何以这种方式编写的示例代码,如果我以这种方式编写代码,会有任何不良影响吗?

您的代码和“示例代码”之间的区别是,在类加载时会实例化您的单例,而在“示例”版本中,在实际需要之前,它不会被实例化。

在后一种情况下,单例对象是在需要之前创建的,但在大多数情况下,这可能并不糟糕

顺便说一下,Joshua Bloch建议(在《有效Java》第2版第3项中)使用单个元素枚举实现单例:

public enum SingletonObject { 
    INSTANCE;
}
他提出以下理由:

[…]它更简洁,提供了序列化 机器免费,并提供 铁一般的多重担保 实例化,即使面对 复杂的序列化或 反射攻击。而这 这种方法尚未被广泛采用, 单元素枚举类型是最好的 实现单例的方法


我认为后一种代码实际上是更标准的模式。您的第一个版本不是线程安全的。使其线程安全的方法包括在每次访问时进行同步,或者非常小心地使其使用双重检查锁定(在Java5内存模型中是安全的,只要正确)

请注意,由于类是惰性初始化的,如果您在类上调用静态方法而不希望创建实例,则后面的代码仍然只会不必要地创建对象

有一种模式使用一个嵌套类来进行初始化,这可能会使它更懒惰,但就我个人而言,第二种形式本身几乎总是做得足够好


在有效的Java中有更多关于这方面的细节,但我恐怕无法找到项目编号。

我认为您的问题在于您混合了单例和延迟初始化。可以使用不同的初始化策略来实现单例:

  • 类加载时的初始化
  • 使用双重检查锁定的延迟初始化
  • 单次检查的延迟初始化(可能重复初始化)
  • 使用类加载器的延迟初始化(holder类习惯用法)

所有这些方法都在中进行了讨论。

我同意Anon,并且在我总是想实例化我将使用的单例的情况下

public class SingletonObject
{
public static SingletonObject REF = new SingletonObject();

private SingletonObject()
{
    // no code req'd
}

}

在第二种形式中,您的singleton是急切地加载的,这实际上是首选形式(第一种形式并不像您自己提到的那样是线程安全的)。急于加载对于生产代码来说并不是一件坏事,但是在某些情况下,您可能希望延迟加载您的单例,正如Guice的作者Bob Lee所讨论的,我在下面引用:

首先,为什么要延迟加载 单身汉?在制作中,你 通常希望急切地加载所有 你的单身汉,所以你抓住了错误 早起并接受任何绩效考核 前面,但在测试和测试期间 开发时,您只想加载 你绝对需要的,以免 浪费时间

在Java1.5之前,我是惰性加载的 单身人士使用普通的旧 同步,简单但有效:

static Singleton instance;

public static synchronized Singleton getInstance() {
  if (instance == null)
    instance = new Singleton();
  return instance;
}
1.5中对内存模型的更改 启用了臭名昭著的双重检查 锁定(DCL)习惯用法。为了实施DCL, 您可以检查中的
volatile
字段 公共路径,仅在以下情况下同步 必要的:

static volatile Singleton instance;

public static Singleton getInstance() {
  if (instance == null) {
    synchronized (Singleton.class) {
      if (instance == null)
        instance = new Singleton();
    }
  }
  return instance;
}
但是
volatile
的速度并没有那么快 比
synchronized
synchronized
是 现在相当快,DCL需要 更多的代码,所以即使在1.5问世之后, 我继续使用纯旧的 同步

想象一下,今天杰里米 曼森指给我看 这需要非常多的时间 代码很少,并且没有 同步开销。零,如在 甚至比volatile更快。碘 需要相同数量的行 代码为普通旧同步,以及 它比DCL快

IODH利用惰性类 初始化。JVM不会执行 类的静态初始值设定项,直到 在课堂上触摸一些东西。 这适用于静态嵌套类, 也在下面的示例中 JVM将不会 初始化
实例
,直到有人 调用
getInstance()

[……]

更新:信用到期时的信用,(版权所有) 2001年)在项目下详细说明了该模式 48它接着指出,您仍然必须使用同步或 非静态上下文中的DCL

我还将singleton处理转换为 我的框架从同步到 DCL,并看到另一个10%的表现 提升(与我开始之前相比) 使用cglib的快速反射)。我只是 在我的微基准测试中使用了一个线程, 因此,对并发性的提升可能是 如果我更换了一个 用一把钥匙紧紧地锁着 相对细粒度的挥发性场 进入


请注意,Joshua Bloch现在建议(自《有效Java》第二版起)使用单个元素
enum
实现单例。第二种方法将解决多线程问题,但即使您不需要,也会始终创建单例。最好的方法是创建一个嵌套类

public class singleton 
{
    private singleton() 
    {
       System.out.println("I'am called only when it's needed");
    }

    static class Nested 
    {
       Nested() {}
       private static final singleton instance = new singleton();
    }

    public static singleton getInstance() 
    {
       return Nested.instance;
    }

    public static void main(String [] args) 
    {
      singleton.getInstance();
    }
}

下面给出了编写单例类的最佳方法。请尝试

public final class SingeltonTest {
    /**
     * @param args
     * @return
     */
    private static SingeltonTest instance = null;

    private SingeltonTest() {
        System.out.println("Rahul Tripathi");
    }

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

在java中实现的不同方法如下

public class SingletonClass {
private SingletonClass= null;    
public static SingletonClass getInstance() {
    if(SingletonClass != null) {
       SingletonClass = new SingletonClass();
    }
  } 
}
这不是线程安全的。以下是单例设计模式的线程安全实现

1。严格同步

private static YourObject instance;

public static synchronized YourObject getInstance() {
    if (instance == null) {
        instance = new YourObject();
    }
    return instance;
}
2.双重检查同步private static YourObject instance; public static synchronized YourObject getInstance() { if (instance == null) { instance = new YourObject(); } return instance; }
private static final Object lock = new Object();
private static volatile YourObject instance;

public static YourObject getInstance() {
    YourObject r = instance;
    if (r == null) {
        synchronized (lock) {    // While we were waiting for the lock, another 
            r = instance;        // thread may have instantiated the object.
            if (r == null) {  
                r = new YourObject();
                instance = r;
            }
        }
    }
    return r;
}
public class Something {
    private Something() {}

    private static class LazyHolder {
        static final Something INSTANCE = new Something();
    }

    public static Something getInstance() {
        return LazyHolder.INSTANCE;
    }
}
public enum Singleton {
    SINGLE;
    public void myMethod(){  
    }
}
// Lazy loading enabled as well as thread safe
                private static class SingletonHolder {
                public static Singleton instance = new Singleton();
                }

                public static Singleton getInstance() {
                   return SingletonHolder.instance;
                  }
               }
class Demo {
  static Demo d=null;

  static {
     d=new Demo();
  }

  private Demo(){
     System.out.println("Private Constructor");
  }

  void add(){
    System.out.println("Hello I am Non-Static");
  }

  static Demo getInstance(){
    return d;
  }