什么是单例模式
单例就是单个对象的意思,指在系统运行期间,一个类最多只能创建一个对象,且该类能自行创建这个对象的一种编码设计模式。
单例模式有两个特点:
- 在系统的整个生命周期内,单例对象最多只能有一个
- 单例对象必须由单例类自行创建,并对外提供访问入口
一个类可以创建多个对象,这是面向对象的语言特性,想要实现单例模式,就要屏蔽这个特性,防止系统可以随意创建类的对象。
要做到这一点,通常做法就是利用private
关键字将类的构造方法私有化,使外部调用者无法利用new
关键字创建类的对象。一旦私有化了类的构造方法,就意味着能够使用new
关键字创建对象的权利只有该类自己拥有!所以该类就必须自己创建单例,并对外界提供可访问该单例对象的静态方法。
为什么是静态方法?因为外界不可能创建单例类的对象,也就没有可能直接调用对象的方法。再进一步可推测出单例对象也要用static
关键字修饰,因为静态方法中无法访问对象成员变量。
单例模式的实现
饿汉模式
单例类加载的时候就创建好单例对象,不管后面会不会使用。
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
懒汉模式
系统启动运行期间不创建单例对象,只在第一次调用单例类入口方法时才去创建单例对象。
特点:不使用不创建,使用时才创建,尽可能延迟单例对象的实例化。
具体代码实现又可分为两大应用场景:线程不安全、线程安全。
线程不安全
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
线程安全
保证线程安全的第一种方式:简单粗暴,直接使用synchronized
静态方法。
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
保证线程安全的第二种方式:双重加锁检查DCL(Double Check Lock)
。
public class Singleton {
// volatile关键字必须有
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {// 第一次校验
synchronized (Singleton.class) {// 加锁
if (singleton == null) {// 第二次校验
singleton = new Singleton();
}
}
}
return singleton;
}
}
双重加锁检查的要点有两个:
- 单例对象需要使用
volatile
修饰,保证单例对象完全初始化后才能被访问到 - 加锁前后,两次检查单例对象是否已被创建,防止多次重复创建
保证线程安全的第三种方式:静态内部类
public class Singleton {
private static class Holder {
private static Singleton singleton = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return Holder.singleton;
}
}
这种方式特点就是不需要加锁,利用内部类延时加载机制达到单例类的延时创建效果,值得推荐和使用!
转载:https://blog.csdn.net/u011506951/article/details/105944193
查看评论