关键词:
【中文标题】线程安全在Java中实现单例模式的有效方法? [复制]【英文标题】:Thread Safe Efficient way to implement singleton pattern in Java? [duplicate] 【发布时间】:2011-05-27 19:42:06 【问题描述】:可能重复:Efficient way to implement singleton pattern in Java
我正在阅读这个Best Singleton Implementation In Java,但它不是线程安全的。
根据维基:
if(singleton==null) synchronized(Singleton.class) // this is needed if two threads are waiting at the monitor at the // time when singleton was getting instantiated if(singleton==null) singleton= new Singleton();
但是 Find Bugs 实用程序在这方面给出了两个错误: 1.双重空检查。 2. 静态字段延迟初始化不正确。
什么是最好的方法,
是否正确:
synchronized (Singleton.class) if (singleton== null) singleton= new Singleton();
【问题讨论】:
这是上述问题的重复;有关详细信息,请参阅该问题。但我不确定这个问题是否有这些有用的链接,所以:About double-checked locking in Java 链接到 these two Java 5 更新。另请参阅 Wikipedia's article on double-checked locking。但对于您的问题的实际答案,请参阅上面链接的问题。 【参考方案1】:制作延迟加载单例的最有效/最简单的方法就是
enum Singleton
INSTANCE
注意:不需要锁定,因为类加载是线程安全的。该类默认为final,不能通过反射调用构造函数。在使用实例或使用类之前,不会创建实例。如果您担心该类可能会被意外使用,您可以将单例包装在内部类中。
final class Singleton
private Singleton()
static class SingletonHolder
static final Singleton INSTANCE = new Singleton();
public static Singleton getInstance()
return SingletonHolder.INSTANCE;
恕我直言,您必须非常偏执才能认为这是一个更好的解决方案。
【讨论】:
在您的第二个代码中,您没有使用enum
,但您使用的是class
,所以我很困惑如何使用它。我想做一个枚举来初始化一个类,下次每次调用那个对象。我该怎么做。你能详细举个例子吗
@Manish 在这种情况下,使用enum
,就像我在第一个示例中所做的那样。
是的,没关系,但我怎样才能只初始化一个类并在下次使用enum
时使用该实例。那是我的困惑。我在哪里看到enum Singleton INSTANCE
这么多,但不知道如何调用和初始化对象
您可以在代码中的任何位置使用Singleton.INSTANCE
。以线程安全的方式调用一次的用于初始化此实例的代码将位于 enum
的构造函数中
@PeterLawrey 你没有忘记你的代码 sn-p 中的私有构造函数 Singleton() 吗?【参考方案2】:
关于这个问题已经写了很多。是的,简单的双重检查锁定模式并不安全。但是您可以通过将静态实例声明为 volatile 来使其安全。新的 Java 内存模型规范在处理 volatile 时为编译器添加了一些代码重新排序限制,因此原来的风险已经消失。
反正我在创建实例时很少真正需要这种惰性,所以我通常只是在类加载时静态地创建它:
private static MyClass instance = new MyClass();
这是简短而清晰的。作为替代方案,如果你真的想让它变得懒惰,你可以利用类加载特性并这样做:
public class MyClass
private static class MyClassInit
public static final MyClass instance = new MyClass();
public static MyClass getInstance()
return MyClassInit.instance;
...
在您第一次调用 getInstance() 之前,不会加载嵌套类。
【讨论】:
【参考方案3】:Efficient way to implement singleton pattern in Java 已接受答案中的第一个代码示例是 线程安全的。 INSTANCE
的创建由类加载器在第一次加载类时执行;它只执行一次,并且以线程安全的方式:
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;
(复制自What is an efficient way to implement a singleton pattern in Java?)
问题中的第二个代码示例是正确且线程安全的,但它会导致每次调用 getInstance()
时同步,从而影响性能。
【讨论】:
不保护私有构造函数是相当偏执的。我假设它避免使用反射创建另一个实例,还是停止内部类调用构造函数? 我正在讨论上一个问题的答案,所以我按原样复制了代码。我个人也会省略if (INSTANCE != null)
检查。
因此我认为是例外。 ;)
您好 Eli,从您的回答中我了解到 Foo 对象将只有一个副本。但是假设两个线程同时调用 getInstance() 函数。那么我相信会有一个比赛条件。如何避免这种情况。因此我们需要避免这种情况。请查看 [link]***.com/questions/15930633/… 以获得最终答案...如何使用工厂构造函数在 Dart 中实现单例模式?
】如何使用工厂构造函数在Dart中实现单例模式?【英文标题】:HowtoimplementSingletonpatterninDartusingfactoryconstructors?【发布时间】:2019-05-2603:15:48【问题描述】:我正在尝试在数据库帮助程序类中实现单例模式,但是,我似乎无法理... 查看详情
如何在qt中实现单例模式
参考技术AQT的单例和其他都是一样的,都是把构造私有,提供访问的方法。声明public:staticdemo*instance();private:demo();staticdemo*m_p;定义demo*demo::m_p=0;demo*demo::instance()if(!m_p)m_p=newdemo;returnm_p; 查看详情
如何在 C# 中实现单例设计模式? [复制]
】如何在C#中实现单例设计模式?[复制]【英文标题】:HowtoimplementsingletondesignpatterninC#?[duplicate]【发布时间】:2014-06-2800:20:24【问题描述】:如何在C#中实现单例设计模式?谁能帮帮我?【问题讨论】:如果你真的需要,请参阅cs... 查看详情
我们是不是需要有持久性对象才能在 php 中实现单例模式
】我们是不是需要有持久性对象才能在php中实现单例模式【英文标题】:Doweneedtohavepersistantobjecttoacheivesingletonpatterninphp我们是否需要有持久性对象才能在php中实现单例模式【发布时间】:2013-02-2815:08:05【问题描述】:我在Singleton... 查看详情
在控制台应用程序 C# 中实现单例的最佳方法?
】在控制台应用程序C#中实现单例的最佳方法?【英文标题】:BestwaytoimplementsingletoninaconsoleapplicationC#?【发布时间】:2009-12-0412:24:26【问题描述】:我有一个基于服务器的控制台应用程序。我只想为特定服务器一次运行它的1个实... 查看详情
如何在 Swift 中实现单例类
】如何在Swift中实现单例类【英文标题】:HowtoImplementSingletonclassinSwift[duplicate]【发布时间】:2016-02-1822:01:56【问题描述】:我是swift编程新手,请告诉我如何使用代码在swift中实现单例类。在obj-c中我知道+(id)sharedManagerstaticMediaMode... 查看详情
在啥情况下我们需要在javascript中实现单例类[重复]
】在啥情况下我们需要在javascript中实现单例类[重复]【英文标题】:Inwhatsituationdoweneedtoimplementsingletonclassinjavsacript[duplicate]在什么情况下我们需要在javascript中实现单例类[重复]【发布时间】:2015-05-1415:53:14【问题描述】:在什么... 查看详情
设计模式:单例模式的三种创建方式及其各自的优缺点
...源上的限制,怎样选择适当的方案来实现单例,以解决多线程的问题。假设使用多个类载入器,可能导致单例失效产生多个实例。双重检查加锁不适用于1.4及更早版本号的java。方式1:packagesingleton;/***同步getInstance()方法:*有点... 查看详情
【kotlin】lazy的线程安全模式
...常量不会多次初始化。但对于Android开发,大部分都属于线程安全(在UI线程里),但lazy默认是线程安全的,会上锁(可以看Java字节码),这样会影响性能。因此需要单独设置LazyThreadSafetyMode(线程安全模式).SYNCHRONIZED同步:只... 查看详情
java设计模式——单例模式
...方式:1)饿汉式(静态常量)2)饿汉式(静态代码块)3)懒汉式(线程不安全)4)懒汉式(线程安全,同步方法)5)懒汉式(线程不安全,同步代码块)6)双重检查7)静态内部类8)枚举 2.1、饿 查看详情
在 Node JS 应用程序中实现单例 mongoDB DB 对象
】在NodeJS应用程序中实现单例mongoDBDB对象【英文标题】:ImplementingsingletonmongDBDBobjectinNodeJSapplication[duplicate]【发布时间】:2018-10-1816:56:59【问题描述】:目前正在使用express,socket.io的nodeJS后端开发,并使用MongoDB作为其数据库。我... 查看详情
线程安全的单例模式
1.全局变量的缺点:必须在程序一开始就创建好对象,如果程序在这次的执行过程中又一直没用到它,就非常耗费资源。 2. 经典的单例模式实现:Java代码publicclassSingleton{//用一个静态变量来记录Singleton类的唯一实例privates... 查看详情
Java - 单例
...间】:2015-07-1801:01:53【问题描述】:我有一些关于在Java中实现单例模式的问题。当我们使用克隆时,可能会有多个单例实例。有什么具体的方法可以预防吗?如果我们使用序列化和反序列化创建另一个单例实例会有什么影响?... 查看详情
单例模式
...个对象存在对象的实例化必须在类中实现一、懒汉模式(线程不安全)packagecom.kevin;//懒汉模式调用静态方法的时候实例化publicclassSingleton1{privateStringname="lazy";privateSingleton1(){}privatestaticSingleton1single=null;//静态工厂方法publicstat 查看详情
unity3d日常开发unity3d中实现单例模式详解(代码片段)
...工具类、实现类,方便脚本调用。下面,就在Unity中实现单例模式。二、实现单例模式2-1、如何实现单例模式首先,来看一下单例模式的UML图:实现流程:1、私有的构造函数,也就是用static静态字段。static... 查看详情
java多线程——单例模式
这篇博客介绍线程安全的应用——单例模式。单例模式 单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例... 查看详情
5java单例模式(线程安全性)(代码片段)
...eton();returninstance;需要实例的时候创建,此方式没考虑线程安全性问题,在多个线程并发调用newInstance()方法,可能会导致创建多个实例 查看详情
线程安全的单例模式(代码片段)
... 双重检查锁与延迟初始化(懒汉式) 在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销,在使用这些对象时才进行初始化。延迟初始化需要注意线程安全 问题,否则就容易出现问... 查看详情