`
nianien
  • 浏览: 16973 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

非线程同步机制下线程安全的单例模式——最优的单例模式

阅读更多
个人认为下面是Java实现的最优的单例模式
这种实现方法采用内部静态类,
只在第一次调用getInstance方法的时候才实例化单例对象
如果不调用,就不会进行单例对象的实例化,
因此,既实现了延迟实例化,又不需要线程同步
引用

public class SingleTon {

private SingleTon(){}

public static SingleTon getInstance() {
return SingleTonHolder.instance;
}

private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}



下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
引用

public class SingleTon {

private SingleTon(){}
         private static SingleTon s=new SingleTon();

public static SingleTon getInstance() {
return s;
}

}



这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用

public class SingleTon {

private SingleTon(){}
private static SingleTon s;

static {
s=new SingleTon();
}

public static SingleTon getInstance() {
return s;
}
}


下面这种就是


还有两种解决方案,不在本帖讨论范围之内
1.采用synchronized的关键字同步getInstance方法
2.采用synchronized的关键字同步代码段,双重是否为空的判断
分享到:
评论
54 楼 theoffspring 2011-05-30  
第一种就行了,比双重锁check要简单。
53 楼 david3083 2011-05-21  
画蛇添足
52 楼 lishaorui 2011-05-20  
单例模式,楼主提到的第一种是比较好的。这些内容在研磨设计模式和漫谈设计模式中都有所讲解,iteye上有他们的博客。
51 楼 java_user 2011-05-20  
nianien 写道
zhang34082 写道
第三种与第一种 是一样的机制,都是通过静态块来初始化的

怎么能是一样的呢?
都说了实例化的时间不一样
第一种,只要你第一次引用了类,都会触发单例对象的实例化
而第三种,只要你不去调用getInsance方法,是不永远不会实例化单例对象的

第三种是类加载的时候就实例化了吧
50 楼 nianien 2011-05-20  
zean 写道
nianien 写道
个人认为下面是Java实现的最优的单例模式
这种实现方法采用内部静态类,
只在第一次调用getInstance方法的时候才实例化单例对象
如果不调用,就不会进行单例对象的实例化,
因此,既实现了延迟实例化,又不需要线程同步
引用

public class SingleTon {

private SingleTon(){}

public static SingleTon getInstance() {
return SingleTonHolder.instance;
}

private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}



下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
引用

public class SingleTon {

private SingleTon(){}
         private static SingleTon s=new SingleTon();

public static SingleTon getInstance() {
return s;
}

}



这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用

public class SingleTon {

private SingleTon(){}
private static SingleTon s;

static {
s=new SingleTon();
}

public static SingleTon getInstance() {
return s;
}
}


下面这种就是


还有两种解决方案,不在本帖讨论范围之内
1.采用synchronized的关键字同步getInstance方法
2.采用synchronized的关键字同步代码段,双重是否为空的判断


========================
Class.forName("SingleTon$SingleTonHolder");

跟你能看到内部类似的~
49 楼 zean 2011-05-19  
nianien 写道
个人认为下面是Java实现的最优的单例模式
这种实现方法采用内部静态类,
只在第一次调用getInstance方法的时候才实例化单例对象
如果不调用,就不会进行单例对象的实例化,
因此,既实现了延迟实例化,又不需要线程同步
引用

public class SingleTon {

private SingleTon(){}

public static SingleTon getInstance() {
return SingleTonHolder.instance;
}

private static class SingleTonHolder{
private static SingleTon instance=new SingleTon();
}
}



下面这种单例模式是应用最多的,同样不存在线程同步的问题
但是,不能实现延迟实例化
引用

public class SingleTon {

private SingleTon(){}
         private static SingleTon s=new SingleTon();

public static SingleTon getInstance() {
return s;
}

}



这种单例模式,和上面的实现差不多,虽然能够延迟单例对象的实例化,但是都是在同一时间范围内完成的
引用

public class SingleTon {

private SingleTon(){}
private static SingleTon s;

static {
s=new SingleTon();
}

public static SingleTon getInstance() {
return s;
}
}


下面这种就是


还有两种解决方案,不在本帖讨论范围之内
1.采用synchronized的关键字同步getInstance方法
2.采用synchronized的关键字同步代码段,双重是否为空的判断


========================
Class.forName("SingleTon$SingleTonHolder");
48 楼 nianien 2011-05-19  
skyuck 写道
nianien 写道
skyuck 写道
nianien 写道
赵精龙 写道
在哪看过,最好的单例模式是只含一个元素的enum

给出代码来,学习一下~



public enum Enum {
	
	INSTANCE;

}


你这代码能说明什么?延迟实例化,还是线程安全?




你自己可以写代码测试一下,你介绍的那几种单例模式  都可以通过反射机制创建出不同的对象,而通过枚举实现的单例则不能

的确不能再被实例化,但是它的实例化是不能延迟的
47 楼 skyuck 2011-05-19  
nianien 写道
skyuck 写道
nianien 写道
赵精龙 写道
在哪看过,最好的单例模式是只含一个元素的enum

给出代码来,学习一下~



public enum Enum {
	
	INSTANCE;

}


你这代码能说明什么?延迟实例化,还是线程安全?




你自己可以写代码测试一下,你介绍的那几种单例模式  都可以通过反射机制创建出不同的对象,而通过枚举实现的单例则不能
46 楼 why213344 2011-05-19  
public enum EnumSingleton implements Serializable {
      INSTANCE;
      public void doSomething() {};
}

书上例子  枚举的单例!新的方法。如果jdk版本允许!
45 楼 guoxu0514 2011-05-19  
记下了!!!
44 楼 nianien 2011-05-19  
skyuck 写道
nianien 写道
赵精龙 写道
在哪看过,最好的单例模式是只含一个元素的enum

给出代码来,学习一下~



public enum Enum {
	
	INSTANCE;

}


你这代码能说明什么?延迟实例化,还是线程安全?
43 楼 kingkan 2011-05-18  
nianien 写道
[quote="sswh]
public static void main(String[] args) throws ClassNotFoundException { 
Class.forName("my.SingleTon", false, Test.class.getClassLoader()); 
System.out.println("做点其他事情..."); 
SingleTon.getInstance(); 
} 
} 

[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。


请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的


在你调用Class.forName("my.SingleTon", false, Test.class.getClassLoader()); ,类装载器装入这个类的时候,该类的静态代码块和静态字段就会初始化。这跟你调用静态方法没有关系,当然啦,你调用这个类的静态方法的时候,类装载器就必须得先装载这个类了,除非这个类不存在,那么装载类,那么内部的静态块就会被初始化。

深入理解JVM书里描述:
引用

Java虚拟机在首次主动使用类型时初始化它们。只有6种活动被认为是主动使用:
创建类的新实例,
调用类中声明的静态方法,
操作类或者接口中声明的非常量静态字段,
调用Java API中特定的反射方法,
初始化一个类的子类,
以及指定一个类作为Java虚拟机启动时的初始化类。
42 楼 skyuck 2011-05-18  
nianien 写道
赵精龙 写道
在哪看过,最好的单例模式是只含一个元素的enum

给出代码来,学习一下~



public enum Enum {
	
	INSTANCE;

}

41 楼 skyuck 2011-05-18  
sswh 写道
nianien 写道

[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。

请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的


好像kingkan说的意思是 类不用实例化也可以调用类的静态方法。
这个说法没错,但和你说的应该不是一个意思。

你说的“调用静态方法,静态代码块和静态字段都会初始化的”,没错,是这样的。

关于类的初始化,在《深入Java虚拟机》中这样描述:

引用

Java虚拟机在首次主动使用类型时初始化它们。只有6种活动被认为是主动使用:
创建类的新实例,
调用类中声明的静态方法,
操作类或者接口中声明的非常量静态字段,
调用Java API中特定的反射方法,
初始化一个类的子类,
以及指定一个类作为Java虚拟机启动时的初始化类。


大概意思是,基本上对类上静态字段、方法的操作都会导致类的初始化。
但除了一种特殊情况以外:
如果使用的是静态常量(static final),并且常量值是一个编译时常量表达式,
这时候不会导致类被初始化。





http://skyuck.iteye.com/blog/902939
40 楼 nianien 2011-05-18  
huanglei7211 写道
nianien 写道
littcai 写道
第一种是延迟加载的,优

从多线程的角度考虑,会不会有并发问题呢?

SingleTon 类在系统启动后就已经创建好了,不会产生并发问题,你可以去了解下静态类

能否给出解释?
39 楼 nianien 2011-05-18  
sswh 写道
nianien 写道

[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。

请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的


好像kingkan说的意思是 类不用实例化也可以调用类的静态方法。
这个说法没错,但和你说的应该不是一个意思。

你说的“调用静态方法,静态代码块和静态字段都会初始化的”,没错,是这样的。

关于类的初始化,在《深入Java虚拟机》中这样描述:

引用

Java虚拟机在首次主动使用类型时初始化它们。只有6种活动被认为是主动使用:
创建类的新实例,
调用类中声明的静态方法,
操作类或者接口中声明的非常量静态字段,
调用Java API中特定的反射方法,
初始化一个类的子类,
以及指定一个类作为Java虚拟机启动时的初始化类。


大概意思是,基本上对类上静态字段、方法的操作都会导致类的初始化。
但除了一种特殊情况以外:
如果使用的是静态常量(static final),并且常量值是一个编译时常量表达式,
这时候不会导致类被初始化。



再次向你致敬,你Java水平比我高,学习了~
38 楼 piao_bo_yi 2011-05-18  
huanglei7211 写道
nianien 写道
littcai 写道
第一种是延迟加载的,优

从多线程的角度考虑,会不会有并发问题呢?

SingleTon 类在系统启动后就已经创建好了,不会产生并发问题,你可以去了解下静态类

必须有并发问题。
37 楼 huanglei7211 2011-05-18  
nianien 写道
littcai 写道
第一种是延迟加载的,优

从多线程的角度考虑,会不会有并发问题呢?

SingleTon 类在系统启动后就已经创建好了,不会产生并发问题,你可以去了解下静态类
36 楼 sswh 2011-05-18  
nianien 写道

[quote name="kingkan"]
调用静态方法或属性不用实例化。
调用对象方法或属性肯定要实例化。

请问kingkan说法对不对?
我测试了一下,即使调用静态方法,静态代码块和静态字段都会初始化的


好像kingkan说的意思是 类不用实例化也可以调用类的静态方法。
这个说法没错,但和你说的应该不是一个意思。

你说的“调用静态方法,静态代码块和静态字段都会初始化的”,没错,是这样的。

关于类的初始化,在《深入Java虚拟机》中这样描述:

引用

Java虚拟机在首次主动使用类型时初始化它们。只有6种活动被认为是主动使用:
创建类的新实例,
调用类中声明的静态方法,
操作类或者接口中声明的非常量静态字段,
调用Java API中特定的反射方法,
初始化一个类的子类,
以及指定一个类作为Java虚拟机启动时的初始化类。


大概意思是,基本上对类上静态字段、方法的操作都会导致类的初始化。
但除了一种特殊情况以外:
如果使用的是静态常量(static final),并且常量值是一个编译时常量表达式,
这时候不会导致类被初始化。


35 楼 nianien 2011-05-18  
赵精龙 写道
在哪看过,最好的单例模式是只含一个元素的enum

给出代码来,学习一下~

相关推荐

Global site tag (gtag.js) - Google Analytics