不考虑线程安全的单例模式
第一步:定义一个private的构造函数,保证这个类不能让其他类new出来。
第二部:定义一个getInstance()里面就是单利模式的核心代码
if(objectDemo==null){
objectDemo = new ObjectDemo();
}
这样一来因为它是静态的属性且其他类不能new,所以每次new 出来的对象是一样的。
以下是一个Demo,来自设计模式之禅:
package com.hyh.pattern;
public class Emperor {
private static Emperor emperor = null; //定义一个皇帝放在那里,然后给这个皇帝名字
private Emperor(){
//世俗和道德约束你,目的就是不让你产生第二个皇帝
}
public static Emperor getInstance(){
if(emperor == null){ //如果皇帝还没有定义,那就定一个
emperor = new Emperor();
}
return emperor;
}
//皇帝叫什么名字呀
public static void emperorInfo(){
System.out.println("我就是皇帝:"+emperor);
}
}
package com.hyh.pattern;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 大臣是天天要面见皇帝,今天见的皇帝和昨天的,前天不一样那就出问题了!
*/
@SuppressWarnings("all")
public class Minister {
/**
* @param args
*/
public static void main(String[] args) {
//第一天
Emperor emperor1=Emperor.getInstance();
emperor1.emperorInfo(); //第一天见的皇帝叫什么名字呢?
//第二天
Emperor emperor2=Emperor.getInstance();
Emperor.emperorInfo();
//第三天
Emperor emperor3=Emperor.getInstance();
emperor2.emperorInfo();
//三天见的皇帝都是同一个人,荣幸吧!
}
}
结果:
考虑并发的单例模式
我们再来熟悉下,不考虑线程安全的单例模式。
public class SingletonPattern {
private static SingletonPattern singletonPattern= null;
//限制住不能直接产生一个实例
private SingletonPattern(){
}
public SingletonPattern getInstance(){
if(this.singletonPattern == null){ //核心
this.singletonPattern = new SingletonPattern(); //核心
} //核心
return this.singletonPattern;
}
}
我们来看核心的那一部分,假如现在有两个线程 A 和线程 B,线程 A 执行到 this.singletonPattern = new SingletonPattern(),正在申请内存分配,可能需要 0.001 微秒,就在这 0.001 微秒之内,线程 B 执行到 if(this.singletonPattern == null),你说这个时候这个判断条件是 true 还是 false?是 true,那然后呢?线程 B 也往下走,于是乎就在内存中就有两个 SingletonPattern 的实例了,看看是不是出问题了?
这时后其中一种方案是:
public class SingletonPattern {
private static final SingletonPattern singletonPattern= new
SingletonPattern();
//限制住不能直接产生一个实例
private SingletonPattern(){
}
public synchronized static SingletonPattern getInstance(){
return singletonPattern;
}
}
直接 new 一个对象传递给类的成员变量 singletonpattern,你要的时候 getInstance()直接返回给
你,解决问题!