单例模式(Singleton pattern)

来源:互联网 发布:乔丹史兰斯基 知乎 编辑:程序博客网 时间:2024/06/07 21:53

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

单例模式的要点有三个:

1、某个类只能有一个实例

2、它必须自行创建这个实例

3、它必须自行向整个系统提供这个实例

下面我们来看一下一个demo

1首先定义一个皇帝 Emperor 

public class Emperor {
private static Emperor emperor = null;//定义一个皇帝,名字为null

private Emperor(){

}

public static Emperor getInstance(){
if(null == emperor){
emperor = new Emperor();
}
return emperor;
}

public static void emperorInfo(){//为这个皇帝(Emperor)起一个名字
System.out.println("【【【【【我是***皇帝】】】】】");
}
}
 

2、接下来定义大臣 Minister

public class Minister {
public static void main(String[] args) {
Emperor emperor1 = Emperor.getInstance();
emperor1.emperorInfo();//第一天上朝拜见的皇帝
Emperor emperor2 = Emperor.getInstance();
emperor2.emperorInfo();//第二天上朝拜见的皇帝

}
}

每天所拜见的皇帝都是同一个皇帝 【通常情况下这样是没有问题的】

在B/S项目中每次Http请求都会在J2EE容器中创建新的线程,每个线程都要创建同一个单例对象,接下来我们分析一下这个单例模式

public class Emperor {
private static Emperor emperor = null;//定义一个皇帝,名字为null

private Emperor(){

}

public Emperor getInstance(){
if(
this.emperor == null){
this.emperor = new Emperor();
}

return this.emperor;
}

public static void emperorInfo(){//为这个皇帝(Emperor)起一个名字
System.out.println("【【【【【我是***皇帝】】】】】");
}
}

假如同时两个Http请求(A和B)过来,线程A的请求在执行 this.emperor = new Emperor(); 这句代码来分配内存时所占用的时间为0.0001秒,在这0.0001秒的同时,线程B请求执行到if(this.emperor == null)此时的if 判断结果是为true,那么内存中将会产生两个 Emperor 实例对象,将会出现数据一致性校验问题,而且在调试代码时很难找出原因。接下来看一下能解决此问题的方法

public class Singleton {
private static Singleton singleton = new Singleton();

private Singleton(){

}
public
 synchronized static Singleton singletonInfo(){
return singleton;
}
}


直接new一个对象传递给成员变量 singleton ,此时再调用singletonInfo() 直接返回就可以了


2 0