单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式有三个要点:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
单例模式是结构最简单的设计模式一,在它的核心结构中只包含一个被称为单例类的特殊类。
单例模式作用:
1.控制资源的使用,通过线程同步来控制资源的并发访问;
2.控制实例产生的数量,达到节约资源的目的。
3.作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。
一、懒汉式单例
而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
二、饿汉式单例
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
public static Singleton1 getInstance() {
return single;
}
}
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,
懒汉式本身是非线程安全的,使用synchronize同步锁可以保证线程安全
synchronized添加在方法上,会把整个方法都锁住,锁的代码太多,锁的粒度太大。
使用双重锁(双重判定锁)可以只锁几行代码,提升性能。
单例模式优缺点
主要优点:
A.提供了对唯一实例的受控访问。
B.由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
C.允许可变数目的实例。
主要缺点:
A.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
B.单例类的职责过重,在一定程度上违背了“单一职责原则”。
C.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。