单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
单例模式有以下特点:
1、单例类只能有一个实例。
2、单例类必须自己自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。
单例模式有三个好处:
1、控制资源的使用,通过线程同步来控制资源的并发访问;
2、控制实例产生的数量,达到节约资源的目的。
3、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。
单例模式有以下特点:
1、单例类只能有一个实例。
2、单例类必须自己自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。
单例模式有三个好处:
1、控制资源的使用,通过线程同步来控制资源的并发访问;
2、控制实例产生的数量,达到节约资源的目的。
3、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。
下面列举一下几种常见的单例模式写法
1.懒汉式
<span style="font-size:12px;">public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}</span>
构造方法为私有的,外部无法访问,只提供一个获取实例的方法给外部调用,方法判断是否已经有该实例,如果没有则创建一个新的,如果有了则返回之前创建的。。
2.饿汉式
<span style="font-size:12px;">public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}</span>
饿汉式解决了多线程的问题,在类初始化的时候就实例化了instance
3.内部静态类
<span style="font-size:12px;"><span style="font-size:10px;">public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}</span></span>
这种方式利用了classloder的机制来保证初始化instance时只有一个线程,它跟饿汉式的区别是 饿汉式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance却不一定被初始化。因为SingletonHolder类没有被主动使用,只有显式通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。
4.枚举
<span style="font-size:12px;">public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}</span>
这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
5.双重校验锁
<span style="font-size:12px;">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;
}
}</span>
这是懒汉式(线程安全版)的升级,不过只有在JDK1.5以后才能实现单例。。。。
说完了单例模式的实现方法,那么单例模式都用在哪里了呢,下面列举一下单例模式的使用场景。
1.Windows的Task Manager(任务管理器)就是很典型的单例模式,不管怎么试,都只能打开一个Windows的任务管理器,类似的还有 Windows的回收站、Windows的我的电脑等等,有兴趣的小伙伴可以试试看,是不是只能打开一个。。。。
2.Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
3.数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。