单例模式,不多说了,这个模式和静态函数有什么区别,之前解释过了,不是今天重点。
这个贴的重点是,单例模式的这个单例,如何初始化。
其实单例的初始化有两种:一种是提前初始化,就是说,在程序使用单例时,先由其他程序保证这个实例已经初始化结束。
这个比较简单,也不是本贴的重点。
另外一种就是程序一开始不初始化,仅仅在单例第一次被调用的时候被初始化。
中间怎么演变就不说了。总之这里技巧是要解决一个矛盾:第一次使用时初始化,就必需要用同步机制,在对象使用前是否已经初始化。
但是加锁后,极大的降低了程序的性能,尤其判断比较复杂的时候。曾经有文章在设计模式界批判“单例是魔鬼”就出于此。
现在很多的补充做法可以尽量的避免这种方式。文字不好解释,给个代码模型吧。
public class Singl{
/**
*单例形成,不允许外部实例化
*/
private Singl(){
}
private static Singl instance;
private Object lock = new Object();
private static Singl getSingl(){
if (instance == null){//第一次判断不要同步
synchronized(lock){//第二次在上锁同步,且要再判断一次
if (instance == null){//第一次判断不要同步
instance = new Singl()
}
}
}
return instance;
}
}
搞定!
还有其他的一些小技巧共享都放到我的空间中了,有兴趣的可以过来看看
这个贴的重点是,单例模式的这个单例,如何初始化。
其实单例的初始化有两种:一种是提前初始化,就是说,在程序使用单例时,先由其他程序保证这个实例已经初始化结束。
这个比较简单,也不是本贴的重点。
另外一种就是程序一开始不初始化,仅仅在单例第一次被调用的时候被初始化。
中间怎么演变就不说了。总之这里技巧是要解决一个矛盾:第一次使用时初始化,就必需要用同步机制,在对象使用前是否已经初始化。
但是加锁后,极大的降低了程序的性能,尤其判断比较复杂的时候。曾经有文章在设计模式界批判“单例是魔鬼”就出于此。
现在很多的补充做法可以尽量的避免这种方式。文字不好解释,给个代码模型吧。
public class Singl{
/**
*单例形成,不允许外部实例化
*/
private Singl(){
}
private static Singl instance;
private Object lock = new Object();
private static Singl getSingl(){
if (instance == null){//第一次判断不要同步
synchronized(lock){//第二次在上锁同步,且要再判断一次
if (instance == null){//第一次判断不要同步
instance = new Singl()
}
}
}
return instance;
}
}
搞定!
还有其他的一些小技巧共享都放到我的空间中了,有兴趣的可以过来看看
解决方案 »
- Robot mouseMove 在Win7下无效,为什么?
- java swing 控件这么少,要用其他控件,不是要自己写吧?
- 小弟快疯了!!!快疯了!!!键盘事件啊!!!
- java 泛型 问题
- 求救:我想做个每次访问页面数字都能加1的程序,请大家帮忙谢谢了!~
- 如何在程序中得出一张表的详细内容?比如主键,外键,什么的
- Thread 同步问题
- 有关让窗口背景变透明的问题????????
- 有趣的小问题(多线程)
- 请问如何在appliction中显示数据库中的图片--〉〉〉〉〉〉〉〉急急急急急急急急
- Can anyone help on this java creation? thanks
- 类反射,字段无序
在多线程环境中可能会产生不止一个的实例。双重检查锁在 JDK 5 以下的版本完全无效。建议采用强制初始化单例成员。在很多资源上都有说明为什么双检锁在 Java 中是无效的:Effective Java
The "Double-Checked Locking is Broken" Declaration
双重检查锁定及单例模式
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
其中,instance = new Singleton(); 的指令码伪码为:
mem = allocate(); //Allocate memory for Singleton object.
instance = mem; //Note that instance is now non-null, but
//has not been initialized.
ctorSingleton(instance); //Invoke constructor for Singleton passing
//instance.换句话说,如果当同步块中执行到伪码:
mem = allocate();
instance = mem;
时(这时对象已经创建,但没初始化),正好另外一个线程进入并执行到为同步的判断块
if (instance == null)时,就会直接返回一个未初始化的对象了。
package single;/**
*
* @author l33187
*/
public class Single {
public static Single s = null;
public static Object lock = new Object();
private int a = 0;
private Single(){
this.a = 100;
}
public Single getSingle(){
if (s == null){
synchronized(lock){
if (s == null){
Single tmp = new Single();
s = tmp;
}
}
}
return s;
}
}
理论上是可以解决问题的,但是在java编译时做的优化。
会将临时变量给优化掉。
但是,我拿反编译工具,查看反编译后的结果,并没有看到优化掉啊?这个优化后的结构怎么看呢?有没有高手知道?