天天看点

Java设计模式(一)—— 单例模式

什么是单例模式?

通俗的讲,就是在应用程序中只需要某个类保留唯一一个实例对象,不希望有更多的实例。单例模式是java设计模式中最简单的设计模式之一,在应用程序中经常被用到。

单例模式的应用场景有很多,比如线程池、日志对象、缓存、数据库连接池、计算机系统设备管理器等等。这些常常都设计成全局唯一的,方便集中管理,也节省系统的开销。

实现单例模式要注意以下三点:

1、单例类只能有一个实例,不能从其他对象中new出来, 即构造器用private修饰。

2、单例类必须自己创建自己的唯一实例,需要实现一个方法提供这个实例。

3、单例类必须能给其他对象提供这一实例。

接下来我们讲讲在Java中如何实现单例模式 :

饿汉式,顾名思义指的是在类加载的时候就初始化好对象,不管有没有用到。

懒汉式和饿汉式相对,指的在程序加载时不初始化对象,什么时候被引用什么时候才初始化对象,即在第一次使用的时候才去初始化对象,可以避免内存浪费。注意在获取实例的getInstance()方法前加上了synchronized关键字,这是为了保证线程安全,避免多线程同一时刻获取对象时造成生成了多个实例。

双重检查锁是在懒汉式基础上演变过来的,当分析懒汉式代码时,你会发现只有在第一次调用获取实例方法时才需要同步。因为仅//2处的代码需要同步,但只有第一次调用才执行此行,后面的其他调用没有执行此行,但都付出了同步的代价。为了提高效率,双重检查锁应运而生,为什么要二次检查,分析双重检查锁代码,当第一次获取实例多个线程并发到达//2处, 第一个线程执行完synchronized的代码块后,后面的线程仍然需要对singleton 进行第二次检查,所以需要对实例对象做两次检查。java内存模型允许无序写入,//4行代码构造器执行之前,变量singleton可能成为非null的,所以singleton需要加上volatile关键字。

这种方式能达到双检锁方式一样的功效,但实现更为简单。这种和饿汉式比较,在类加载时,singleton实例并没有被初始化,需要显示调用getInstance()方法才会转载SingleHolder类,从而初始化singleton实例,所以达到了延时加载的效果。此方法在实际使用中用的最多,推荐此种写法。

这种方式巧妙的应用了枚举的特点,构造器本身私有,写法简单,自动支持序列化机制,防止多次实例化,获取实例可以通过Singleton.INSTANCE来访问。

方式

是否支持延时初始化

实现难度

线程安全

饿汉式

不支持

简单

安全

懒汉式

支持

双重检查锁

复杂

静态内部类

一般

枚举