论坛首页 Java企业应用论坛

对于单例模式的一点想法

浏览 23658 次
精华帖 (1) :: 良好帖 (9) :: 新手帖 (11) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-07-07  
	public static SysRoleDAO getInstance() {
		if (sysRole == null) {
			synchronized (SysRoleDAO.class) {
				if (sysRole == null) {
					SysRoleDAO _sysRole = new SysRoleDAO();
					sysRole = _sysRole;
				}
			}
		}
		return sysRole;
	}


试试这样
0 请登录后投票
   发表时间:2008-07-07  
icewubin 写道

但是
public static final Singleton INSTANCE=new Singleton();

这种模式的话,对这个类的任何访问都会触发,比如这个类有什么全局常量的访问,也会触发初始化,但是此时根本不需要初始化。


你这种说法不知道有什么证据?
我以前也和你一样,想当然这样认为“对这个类的任何访问都会触发,比如这个类有什么全局常量的访问,也会触发初始化”,但我做了个小实验,SUN JDK1.6下(JDK1.5一样):

package test;

public class Singleton {
	public static final String NAME = "test";
	private static final Singleton INSTANCE = new Singleton();

	private Singleton() {
		System.out.println("Invoke constructor.");
	}

	public static Singleton getInstance() {
		return INSTANCE;
	}
}

package test;

public class Test1 {

	public static void main(String[] args) throws Exception {
		System.out.println(Singleton.NAME);
		System.out.println("-------------------");
		Singleton.printString("Test static method.");
	}

}

执行结果如下:
test
-------------------
Invoke constructor.
Test static method.


说明调用Singleton.NAME常量是不会触发此类其他静态变量的初始化的,(即单例也不会被初始化)。
调用静态方法则会。

0 请登录后投票
   发表时间:2008-07-07  
Lucas Lee 写道
你这种说法不知道有什么证据?
我以前也和你一样,想当然这样认为“对这个类的任何访问都会触发,比如这个类有什么全局常量的访问,也会触发初始化”,但我做了个小实验,SUN JDK1.6下(JDK1.5一样):

package test;

public class Singleton {
	public static final String NAME = "test";
	private static final Singleton INSTANCE = new Singleton();

	private Singleton() {
		System.out.println("Invoke constructor.");
	}

	public static Singleton getInstance() {
		return INSTANCE;
	}
}

package test;

public class Test1 {

	public static void main(String[] args) throws Exception {
		System.out.println(Singleton.NAME);
		System.out.println("-------------------");
		Singleton.printString("Test static method.");
	}

}

执行结果如下:
test
-------------------
Invoke constructor.
Test static method.


说明调用Singleton.NAME常量是不会触发此类其他静态变量的初始化的,(即单例也不会被初始化)。
调用静态方法则会。


static final会直接编译成常量,也就是Test1中的Single.NAME其实是直接初始化成常量,并没有调用到Singleton。看看这个帖子 http://www.iteye.com/topic/211937
0 请登录后投票
   发表时间:2008-07-08  
lt0604 写道
单例在分布式应用中应该特别注意!


分布式应用中,单例干脆就别用了,即使用了也就是节省点内存的用途了。
1 请登录后投票
   发表时间:2008-07-08  
多谢举出反例,不过即使如此,之前说的lazy的程度不一样还是成立的。

没想到JVM对static final的常量优化的如此彻底啊。
0 请登录后投票
   发表时间:2008-07-09  
dennis_zane 写道
Lucas Lee 写道
你这种说法不知道有什么证据?
我以前也和你一样,想当然这样认为“对这个类的任何访问都会触发,比如这个类有什么全局常量的访问,也会触发初始化”,但我做了个小实验,SUN JDK1.6下(JDK1.5一样):

package test;

public class Singleton {
	public static final String NAME = "test";
	private static final Singleton INSTANCE = new Singleton();

	private Singleton() {
		System.out.println("Invoke constructor.");
	}

	public static Singleton getInstance() {
		return INSTANCE;
	}
}

package test;

public class Test1 {

	public static void main(String[] args) throws Exception {
		System.out.println(Singleton.NAME);
		System.out.println("-------------------");
		Singleton.printString("Test static method.");
	}

}

执行结果如下:
test
-------------------
Invoke constructor.
Test static method.


说明调用Singleton.NAME常量是不会触发此类其他静态变量的初始化的,(即单例也不会被初始化)。
调用静态方法则会。


static final会直接编译成常量,也就是Test1中的Single.NAME其实是直接初始化成常量,并没有调用到Singleton。看看这个帖子 http://www.iteye.com/topic/211937



是这样的,访问static final不属于主动调用。
0 请登录后投票
   发表时间:2008-07-10  
再集群环境下怎么实现单例模式?
0 请登录后投票
   发表时间:2008-07-10  
这样可能会好一点.
	private static HashCodeDigest instance = null;

	private HashCodeDigest() {
	}

	private static synchronized void syncInit() {
		if (instance == null) {
			instance = new HashCodeDigest();
		}
	}

	public static HashCodeDigest getInstance() {
		if (instance == null) {
			syncInit();
		}
		return instance;
	}
0 请登录后投票
   发表时间:2008-07-10  
lefish 写道
这样可能会好一点.
	private static HashCodeDigest instance = null;

	private HashCodeDigest() {
	}

	private static synchronized void syncInit() {
		if (instance == null) {
			instance = new HashCodeDigest();
		}
	}

	public static HashCodeDigest getInstance() {
		if (instance == null) {
			syncInit();
		}
		return instance;
	}

你这个就是我在最开始提到的普通的double-checking的做法,static synchronized method等效于synchonized(Singleton.class).
一样会有问题。
0 请登录后投票
   发表时间:2008-07-14  
Lucas Lee 写道
slangmgh 写道

JVM 不保证代码INSTANCE=new Singleton() 一定在hasInitialized=1之前执行!!!

这个不会吧?你的证据呢?
我提到的out-of-order write只是对INSTANCE=new Singleton()范围而言。
连两条语句的顺序都无法保证,这个就难以想象了。。。


确实有这个可能的,如果两条语句的顺序改变不会影响执行结果,编译器有可能为某种优化对其进行顺序调整,我在《java concurrecy in practice》中看到的。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics