单例的四种实现方式
一、什么是单例模式?
1、定义
Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。
从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责
2、单例模式的优点
1)在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例
2)单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3)提供了对唯一实例的受控访问。
4)由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式 无疑可以提高系统的性能。
5)允许可变数目的实例。
6)避免对共享资源的多重占用。
3、单例模式的应用场景
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:
1)需要频繁实例化然后销毁的对象。
2)创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3)有状态的工具类对象。
4)频繁访问数据库或文件的对象。
以下都是单例模式的经典使用场景:
1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
2)控制资源的情况下,方便资源之间的互相通信。如线程池等
二、单例的四种实现方式
1、饿汉式
饿汉式: 在类装载的时候就急速的初始化,饿汉式是线程安全的、 但是没有延迟加载
/**
* 饿汉式
*/
class Singleton_one {
// 1、私有化构造器
private Singleton_one() {
}
// 2、初始化
private static Singleton_one instance = new Singleton_one();
public static Singleton_one getInstance() {
return instance;
}
}
2、懒汉式(同步方法)
单纯的懒汉式是存在线程安全问题的、需要我们使用同步策略
/**
* 懒汉式(同步方法)
*/
class Singleton_two {
// 1、私有化构造器
private Singleton_two() {
}
private static Singleton_two instance = null;
public synchronized static Singleton_two getInstance() {
if (instance == null) {
instance = new Singleton_two();
}
return instance;
}
}
3、懒汉式(Dubbo Check)
单纯的懒汉式是存在线程安全问题的、需要我们使用同步策略、这里使用了双重校验
/**
* 懒汉式(Double Check)
*/
class Singleton_three {
// 私有化构造器
private Singleton_three() {
}
private static Singleton_three instance = null;
public static Singleton_three getInstance() {
if (instance == null) {
synchronized (Singleton_three.class) {
if (instance == null) {
instance = new Singleton_three();
}
}
}
return instance;
}
}
4、静态内部类
1)静态内部类的加载时机
- 外部类初次加载,会初始化静态变量、静态代码块、静态方法,但不会加载内部类和静态内部类。
- 实例化外部类,调用外部类的静态方法、静态变量,则外部类必须先进行加载,但只加载一次。
- 直接调用静态内部类时,外部类不会加载。
/**
* 内部类实现单例模式
* <p>
* 既不用加锁 、也能实现懒加载
*
*
* 外部类初次加载的时候不会加载内部类和静态内部类
*/
class Singleton_four {
private static int a = 10;
// 私有化构造器
private Singleton_four() {
}
private static class Inner {
static Singleton_four instance = new Singleton_four();
}
public static Singleton_four getInstance() {
return Inner.instance;
}
}