单例模式:确保某个类的实例有且只有一个
特点:
-
单例模式只能有一个实例。
-
单例类必须创建自己的唯一实例。
-
单例类必须向其他对象提供这一实例。
实现方式:
(一):饿汉式
public class Singleton1 {
// 饿汉式 : 类加载时就创建对象,天生线程安全
static final Singleton1 instance = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return instance;
}
}
(二):懒汉式
class Singleton2 {
// 懒汉式 : 不用时不创建
// 线程不安全
private static Singleton2 instance = null;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
由于线程不安全,因此需要加锁
(三)加锁懒汉式:
public class Singleton2 {
// 懒汉式 : 不用时不创建
// 线程不安全,需要同步操作
// 加锁影响性能
private static volatile Singleton3 instance = null;
private Singleton3() {
}
public static synchronized Singleton3 getInstance() {
if (instance == null) {
instance = new Singleton3();
}
return instance;
}
}
(四)双重检查锁:
class Singleton4{
// 双重检查锁
private static volatile Singleton4 instance;
private Singleton4() {
}
public static Singleton4 getInstace() {
if(instance == null ) {
synchronized(Singleton4.class) {
if(instance == null) {
instance = new Singleton4();
}
}
}
return instance;
}
}
在并发时,双重检查锁的情景:
STEP 1. 线程A访问getInstance()方法,因为单例还没有实例化,所以进入了锁定块。
STEP 2. 线程B访问getInstance()方法,因为单例还没有实例化,得以访问接下来代码块,而接下来代码块已经被线程1锁定。
STEP 3. 线程A进入下一判断,因为单例还没有实例化,所以进行单例实例化,成功实例化后退出代码块,解除锁定。
STEP 4. 线程B进入接下来代码块,锁定线程,进入下一判断,因为已经实例化,退出代码块,解除锁定。
STEP 5. 线程A初始化并获取到了单例实例并返回,线程B获取了在线程A中初始化的单例。
理论上双重校验锁法是线程安全的,并且,这种方法实现了lazyloading。
(五):静态内部类写法
class Singleton5{
// 使用内部类 用时再创建
// 天生线程安全
private static class Holder {
private static final Singleton5 instance = new Singleton5();
}
private Singleton5() {
}
public static Singleton5 getInstance() {
return Holder.instance;
}
}
(六):枚举法创建单例,代码最简洁的一种写法
public enum Singleton6{
instance;
public void whateverMethod(){}
}
调用时只需Singleton6.instance
即可
上面提到的其他几种实现单例的方式都有共同的缺点:
1)需要额外的工作来实现序列化,否则每次反序列化一个序列化的对象时都会创建一个新的实例。
2)可以使用反射强行调用私有构造器(如果要避免这种情况,可以修改构造器,让它在创建第二个实例的时候抛异常)。
而枚举类很好的解决了这两个问题,使用枚举除了线程安全和防止反射调用构造器之外,还提供了自动序列化机制,防止反序列化的时候创建新的对象。
关于枚举类更详细的内容可以参考下面的文章
https://blog.csdn.net/javazejian/article/details/71333103