单利模式:确保一个类最多只有一个实例,并提供一个全局访问点。
经典单利模式创建对象代码
public class Singleton { private static Singleton uniqueInstance = null; private Singleton(){ } public static Singleton getInstance(){ if (uniqueInstance==null) { uniqueInstance=new Singleton(); } return uniqueInstance; } }
问题:多线程
public class Q { //多线程 private static Q uniqueInstance = null; private Q(){ } public static Q getInstance(){ if (uniqueInstance==null) {//当线程1执行此语句后,判断通过, /*正准备执行uniqueInstance=new Q()时,线程2抢占到了cpu资源, *切换到线程2开始执行,线程2会发现uniqueInstance还是null,所以会创建对象,创建完后, *而当切换到线程1时,发现线程1已经进入if判断,所以也会创建一个新uniqueInstance, *此时线程1创建的uniqueInstance和线程2创建的uniqueInstanc是不一样的 **/ uniqueInstance=new Q(); } return uniqueInstance; } }
解决办法
1、创建对象的方法加同步锁
/** * 优化方式1 * 方法添加同步锁 * 优点:使用方便 * 缺点:当线程很多的情况下,非常耗费资源 * @author yxm * */ public class Optimization_Singleton_1 { private static Optimization_Singleton_1 uniqueInstance = null; private Optimization_Singleton_1(){ } public synchronized static Optimization_Singleton_1 getInstance(){ if (uniqueInstance==null) { uniqueInstance=new Optimization_Singleton_1(); } return uniqueInstance; } }
2、饿汉式创建对象
/** * 优化方式2 * 急切创建对象 * 优点:不会因为加锁而耗费资源 * 缺点:当不使用此类时,照样会耗费内存 * @author yxm * */ public class Optimization_Singleton_2 { private static Optimization_Singleton_2 uniqueInstance = new Optimization_Singleton_2(); private Optimization_Singleton_2(){ } public static Optimization_Singleton_2 getInstance(){ if (uniqueInstance==null) { uniqueInstance=new Optimization_Singleton_2(); } return uniqueInstance; } }
3、双重检查加锁 (较完美)
/** * 优化方式3 * 双重检查加锁 * 较完美 * @author yxm * */ public class Optimization_Singleton_3 { private volatile static Optimization_Singleton_3 uniqueInstance = null;//volatile给编译器使用,保证线程安全 private Optimization_Singleton_3(){ } public synchronized static Optimization_Singleton_3 getInstance(){ if (uniqueInstance==null) { //只有等线程1把对象创建好了,其他线程才会进入以下代码块 synchronized(Optimization_Singleton_3.class){ if (uniqueInstance==null) { uniqueInstance=new Optimization_Singleton_3(); } } } return uniqueInstance; } }
案例:一个巧克力工厂,生产各式各样的巧克力,生产过程有(准备原料、填充、加热、排出)四道工序,但是现在工厂里只有一条生产线,意味着一次只能生产一种巧克力,请问如何把控?
分析:转换为计算机思维,此场景是典型的一个类只能有一个对象,符合单利模式特征
普通巧克力工厂
public class ChocolateFactory { private boolean empty; private boolean boiled; public ChocolateFactory(){ empty=true; boiled=false; } //填充 public void fill(){ if (empty) { empty=false; boiled=false; } } //加热 public void boil(){ if (!boiled) { boiled=true; } } //排出 public void drain(){ if (!empty&&boiled) { empty=true; } } }
使用单利模式后的巧克力工厂
public class ChocolateFactoryInSingleton { private boolean empty; private boolean boiled; public static ChocolateFactoryInSingleton uniqueInstance=null; private ChocolateFactoryInSingleton(){ empty=true; boiled=false; } public static ChocolateFactoryInSingleton getInstance(){ //此处确保不同的巧克力不会进入同一条生产线 if (uniqueInstance==null) { uniqueInstance=new ChocolateFactoryInSingleton(); } return uniqueInstance; } //填充 public void fill(){ if (empty) { empty=false; boiled=false; } } //加热 public void boil(){ if (!boiled) { boiled=true; } } //排出 public void drain(){ if (!empty&&boiled) { empty=true; } } }
时间: 2024-10-31 19:50:51