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