单例模式
单例模式:确保一个类只有一个实力,并提供一个全局访问点。
内容其实就是实例化一个对象(唯一一个),然后提供接口供全局访问。
那么,为什么只要一个唯一对象:比如线程池,缓存,对话框只需要一个对象,因为如果有多个对象会导致类似数据访问不一致,行为异常(就像多线程访问共享数据
而导致数据的不一致那样)。
那么,为什么不适用静态static:拥有static 方便并且没有 static 全局变量的缺点。static 必须在程序一开始就创建好对象,而单件模式可以在需要的时候创建。(如果不需要改对象,那么就不会创建----延迟实例化),并且全局变量并不能确保只有一个实例。
简单的单例模式:
public class Singleton{ private static Singleton uniqueInstance; //利用静态变量来就Singleton类的唯一实力 private Singleton(){ //构造器定义为私有,这样外部不能调用该构造器。只能自己用。 } public static Singleton getInastace(){ //此方法获取uniqueInstache 对象 if(uniqueInstance == null){ //不为空,实例化 uniqueInstance = new Singleton; } return uniqueInstance; } }
这就是一个简单的单件模式,是不是很简单。当需要用到该对象的时候就用 getInstance()方法,如果没创建就创建一个返回,如果已经创建就把原来的返回。
但是,这样也并不是真正的单件模式。 在多线程里面,线程是随机切换的。完全有可能导致 线程a执行到if(uniqueInstance == null) 后切换到线程B.
线程b执行返回 uniqueInstance后再次回到线程a,导致出现两个对象。
有问题就解决:1.在java里面解决线程同步问题可以使用synchronized关键字。
public static synchronized Singleton getInastace(){ //此方法获取uniqueInstache 对象 if(uniqueInstance == null){ //不为空,实例化 uniqueInstance = new Singleton; } return uniqueInstance; }
这样这个方法就被同步,在线程a执行完毕之前,线程b不会进入。
再想想,获取单件对象是随时的,而同步方法会严重拖垮性能。同步一个方法可能造成程序执行效率下降100倍。
如果 getInstance()的性能对应用程序不是很关键,就可以使用该方法,简单省事。、
2.使用"急切"创建实例,而不用延迟实例化的做法
public class Singleton{ private static Singleton unqueInstance = new Singleton();//保证线程安全 private Singleton(){} public static Singleton getInstance(){ return uniqueInstance; } }
这样就保证了线程的安全,当需要使用单件对象时,调用getInstance()就可以返回该对象。
3."双重检查加锁(double-checked locking)"
public class Singleton{ private volatile static Singleton uniqueInstance; private SIngleton(){} public static Singleton getInstance(){ if(uniqueInstance == null){ synchronized (singleton.class){ if(uniqueInstance = null){ uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地处理uniqueInstance变量。
双重检查加锁,在第一次创建时使用同步方法确保线程安全。在以后的调用中就不需要同步方法了。
单件模式:一个私有的构造器,一个静态方法,一个静态变量。