什么是单例模式
- 单例模式(Singleton Pattern)是一个比较简单的模式,实际应用很广泛,比如 Spring 中的
Bean
实例就是一个单例对象。 - 定义:确保某一个类 只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式的优缺点
- 评价任何一种事务都要从两个方面去看,不能单一的评价。下面来看看单例模式有什么优缺点。
优点
- 只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
- 单例模式可以避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在 内存中,避免对同一个资源文件的同时写操作。
- 单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单 例类,负责所有数据表的映射处理。
缺点
- 单例模式一般没有接口,很难扩展(根据环境而定)。
- 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心是否是单例的。
单例模式的实现
- 单例模式有很多的实现方式,但是各种实现的方式都有其优缺点,下面来看看各种的实现方式。
-
单例模式的实现满足以下几点:
- 构造方法私有。
- 有一个静态方法获取该类的实例。
- 该类保证只有一个实例。
懒汉式
- 懒汉式是当用到这个对象的时候才会创建。
- 优点:只有用到的时候才会创建这个对象,因此节省资源。
- 简单的实现如下:
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
- 上面的代码算是基本满足了单例模式,但是不能满足线程安全,一旦在多线程的环境下仍然是不能保证该类是单例的。
- 如何保证线程安全,当然是加锁了,我们可以加线程同步锁
synchronized
,实现如下:
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
- 此种实现方式虽然满足了线程安全,但是加锁势必会影响性能。
饿汉式
- 饿汉式和懒汉式恰巧相反,在类加载的时候就创建实例。
- 优点:还没用到就创建,浪费资源。
- 缺点:在类加载的时候就创建,线程安全。
- 实现如下:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
双重校验锁
- 属于懒加载的一种实现方式,采用双重校验的机制,在多线程的情况仍然保持高性能。
- 实现如下:
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
匿名内部类/静态内部类
- 利用静态变量、静态代码块、静态方法都是在类加载的时候只加载一次的原理。
- 实现如下:
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
总结
- 单例模式的实现虽然很简单,但是也要确保实现的性能和线程安全的问题。
- 单例模式的实现主流的就是以上介绍的几种,分别是
懒汉式线程不安全
、懒汉式线程安全
、饿汉式
、双重校验锁的实现
、静态内部类的实现
。这几种方式各有优缺点,陈某推荐使用静态内部类的实现方式。 - 单例模式也是Spring使用的一种设计模式,保证了
Bean
的单实例才能管理和监控Bean的创建和销毁。
本文使用 mdnice 排版
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。