单例模式的意义
有些对象我们只需要一个:线程池 缓存 硬件设备等
如果多个实例会有造成冲突、结果的不一致性等问题
是否可以用静态变量方式实现?
或者coder之间协商个全局变量
单例模式:确保一个类最多只有一个实例,并提供一个全局访问点
经典单例类的Java代码
一个简单的巧克力工厂项目代码
package com.java.jikexueyuan.singleton;
public class Singleton {
private static Singleton uniqeInstance=null;
private Singleton(){
};
public static Singleton getInstance()
{
if(uniqeInstance==null)
{
uniqeInstance=new Singleton();
}
return uniqeInstance;
}
}
在这里定义了一个私有的构造方法,也就是说,在这个类的外面无法使用new Singelton的方法来新建一个实例,只有在Singleton自己里面才能新建一个实例。这样就保证里,全局只有一个Singleton实例,
其他的对象可以使用getInstance这个静态方法来调用实例。
巧克力工厂实例
package com.java.jikexueyuan.singleton;
public class ChocolateFactory {
private boolean empty;
private boolean boiled;
public volatile static ChocolateFactory uniqueInstance = null;
private ChocolateFactory() {
empty = true;
boiled = false;
}
public static ChocolateFactory getInstance() {
if (uniqueInstance == null) {
synchronized (ChocolateFactory.class) {
if (uniqueInstance == null) {
uniqueInstance = new ChocolateFactory();
}
}
}
return uniqueInstance;
}
public void fill() {
if (empty) {
// 添加原料巧克力动作
empty = false;
boiled = false;
}
}
public void drain() {
if ((!empty) && boiled) {
// 排出巧克力动作
empty = true;
}
}
public void boil() {
if ((!empty) && (!boiled)) {
// 煮沸
boiled = true;
}
}
}
比如现在有两个工厂来做巧克力,但是只有一个锅,所以只能是有一个锅的实例,创建单例的巧克力工厂,fill如果锅是空的,那么久进行煮沸 推出的行为。这样做的好处就是,如果每一个巧克力工厂都创建了自己实例,那么这个锅也会有两个实例,这样就和逻辑相背离了。
多线程问题
那么再多线程中,就有可能出现一条线程创建实例的时候判断完singleton类是不是空的,这时还没有创建实例,然后系统的时间片转交给了另一个线程,这条线程判断实例是空的,那么它创建了一个实例,然后时间片交回给第一条线程的时候,他继续执行又回创建一个实例,这样就bug了
结局方案:将getInstance方法同步 (synchronized)getInstance 也就使用java的synchronized方法将实例化方法同步化。