单例模式的五种实现方式
来源:互联网 发布:先锋网络av功放接收机 编辑:程序博客网 时间:2024/05/13 12:00
1.最容易想到的方式
public class Singleton {
private static final Singleton INSTSNCE = new Singleton();//单例
private Singleton(){//构造函数私有
}
public static Singleton getInstance(){
return INSTSNCE;
}
public static void main(String[] args){
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
优点是:简单
缺点是:无论用没用到INSTSNCE,都会进行初始化。
2.延迟加载(lazy-load)
public class Singleton2 {
private Singleton2(){
}
private static Singleton2 INSTANCE ;
public synchronized static Singleton2 getInstance(){//同步方法,效率低
if(INSTANCE == null){//lazy-loaded
INSTANCE = new Singleton2();
}
return INSTANCE;
}
public static void main(String[] args){
Singleton2 s1 = Singleton2.getInstance();
Singleton2 s2 = Singleton2.getInstance();
System.out.println(s1 == s2);
}
}
优点:做到了延迟加载,也可以说是按需加载
缺点:方法同步,效率低
3.Double-Check-Lock
public class Singleton3 {
private Singleton3(){
}
private volatile static Singleton3 instance;//volatile,保证可见性。各个线程的工作存储器和主存保持一致
public static Singleton3 getInstance(){//double-check-lock
if(instance == null){
synchronized(Singleton3.class){
if(instance == null){
instance = new Singleton3();
}
}
}
return instance;
}
public static void main(String[] args){
Singleton3 s1 = Singleton3.getInstance();
Singleton3 s2 = Singleton3.getInstance();
System.out.println(s1 == s2);
}
}
注意这里的“volatile”关键字,我们知道jdk1.4以前,DCL是无法保证正常工作的,但是从jdk5开始,把instance定义成volatile就可以保证正常工作了。
为什么1.4以前,DCL不能正常工作,这主要跟jvm的内存模型有关。这就说来话长了,jvm把内存分为两类,主存储器和工作存储器,主存储器只有一份,但是,每一个线程都有自己的工作存储器,线程不能直接操纵主存储器,都是把主存里面的值拷贝到自己的工作存储器,然后操作自己的工作存储器,然后在适当的时候,写回到主存储器里面。volatile就保证了所有的线程的工作存储器和主存储器是一致的。
优点:延迟加载
缺点:只需要一次同步
4. Initialization on Demand Holder idiom
public class Singleton4 {
private static class Singleton4Holder{//容器
public static Singleton4 instance = new Singleton4();
}
private Singleton4(){
}
public static Singleton4 getInstance(){
return Singleton4Holder.instance;
}
public static void main(String[] args) {
Singleton4 s1 = Singleton4.getInstance();
Singleton4 s2 = Singleton4.getInstance();
System.out.println(s1 == s2);
}
}
类载入到jvm的时候,会进行初始化,但是只会初始化static成员和static代码块,而不会初始化静态内部类的成员。因此,只有实际调用getInstance的时候,才会初始化静态内部类的静态成员。做到了延迟加载。同时,jvm的类加载机制保证了绝对不会出现同步问题,避免了双检查锁。
优点:延迟加载,而且不需要同步。
5.Enum
enum SingletonEnum {
INSTANCE {
public void someMethod() {
System.out.println("do something!");
}
};
protected abstract void someMethod();
}
public class Singleton5{
public static void main(String args[]){
SingletonEnum s1= SingletonEnum.INSTANCE;
s1.someMethod();
SingletonEnum s2= SingletonEnum.INSTANCE;
System.out.println(s1 == s2);
}
}
还有比这个更简洁明了的吗?
- 单例模式五种实现方式
- 单例模式的五种实现方式
- 单例模式的五种实现方式
- 单例模式的五种实现方式
- ANDROID设计模式之单例模式的五种实现方式
- JAVA设计模式-单例模式(Singleton)的五种实现方式
- java单例模式五种实现方式
- 单例的五种实现方式,及其性能分析。
- 单例的五种实现方式,及其性能分析。
- 单例的五种实现方式,及其性能分析
- 单例模式的五种实现形式
- 实现单例模式的五种方法
- 五种方法实现Java的Singleton单例模式
- 单例模式的多种实现方式
- 单例模式的多种实现方式
- 单例模式的实现方式
- java单例模式的实现方式
- Python单例模式的实现方式
- MFC窗体设计 转
- Session详解 作者:郎云鹏
- 百度笔试题9.2
- 一、Struts 2 基础---2.web.xml的配置
- 存储过程及序列的例子
- 单例模式的五种实现方式
- 百度笔试题9.3
- 一、struts 2 基础---3.struts.xml的配置
- 百度笔试题10
- SCRUM敏捷项目管理
- 一、Struts 2 基础---4.Struts 2中的Action
- 百度笔试题10.2
- 百度笔试题10.3
- COleDropTarget类支持任意窗口拖放