单例模式

来源:互联网 发布:手机打牌赚钱软件 编辑:程序博客网 时间:2024/06/06 00:58

1.意图

保证一个类仅有一个实例,并提供一个访问全局访问点

2.动机

有一些对象仅能创建一个,例如:线程池,缓存,对话框,日志对象,打印机等设备的驱动程序的对象,那么如何创建一个受控访问的唯一实例的类呢?这时候就能用到了单例

3.定义

单例模式(单件模式)确保一个类只有一个实例,并提供一个全局访问点
4.实现
组成:
  • 设置构造器访问权限为private,确保其他人使用构造器
  • 生成唯一实例
  • 提供全局访问点,也就是提供一个公有静态方法作为访问接口
代码实现
public class Singleton {//生成唯一实例private static final Singleton uniqueInstantce = new Singleton(); //设置构造器为privateprivate Singleton() {} //提供一个公有静态方法作为访问接口public static Singleton getInstance() { return uniqueInstantce;}}
上面是实现单例模式最简单的方式 还有为解决下面问题产生的变种 

延迟加载
当创建这个实例的开销过大时,第一种方式无论使用或否都会创建这个实例,带来额外负担。 这时就要考虑是否在使用延迟加载了。 
代码
public class Singleton {//先不创建实例private static Singleton uniqueInstantce; //设置构造器为privateprivate Singleton() {} //提供一个公有静态方法作为访问接口public static Singleton getInstance() { //如果为空,就新建一个if(uniqueInstantce == null)uniqueInstantce = new Singleton();return uniqueInstantce;}}

但是上面的延迟加载方式在多线程下会出现问题

当线程1执行到 if(uniqueInstantce == null) 这句时,此时uniqueInstantce为空,但在执行uniqueInstantce = new Singleton()前线程切换
到线程2,此时uniqueInstantce还是空,就一直执行下去,返回单例。这时再切换回线程1去执行执行uniqueInstantce = new Singleton(),
这时就创建了两个实例


为了解决多线程下的问题

使用synchronized关键字修饰静态方法

public class Singleton {//先不创建实例private static Singleton uniqueInstantce; //设置构造器为privateprivate Singleton() {} //提供一个公有静态方法作为访问接口public static synchronized Singleton getInstance() { //如果为空,就新建一个if(uniqueInstantce == null)uniqueInstantce = new Singleton();return uniqueInstantce;}}

使用volatile, synchronized关键字双重加锁

public class Singleton {//先不创建实例private static volatile Singleton uniqueInstantce; //设置构造器为privateprivate Singleton() {} //提供一个公有静态方法作为访问接口public static Singleton getInstance() { //如果为空,就新建一个if(uniqueInstantce == null) {synchronized(Singleton.class) {if(uniqueInstantce == null) uniqueInstantce = new Singleton();}}return uniqueInstantce;}}

使用枚举

单元素的枚举类型已经成为实现singleton的最佳方法 -- 《Effective Java》

public enum Singleton {INSTANCE; public void method() {}public void method2() {}public void method3() {}}
0 0
原创粉丝点击