用Java编写单例的不同方法
用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
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;
}