单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
通常单例模式在Java语言中,有两种构建方式:
K1VK78.png
三大要素:
①饿汉式单例(线程安全)
阐述:见名知义,“饿汉”说明它很“饥饿”,迫切需要找到吃的,这里也就是我们所说的实例。为什么说它是线程安全的呢?因为我们一开始就创建一个这样的实例,其他线程在访问前这个实例就已经创建完成,在类的生命周期中只创建一次,所以饿汉单例天生就是线程安全的。
// 饿汉式单例示例
class Singletone {
private static Singletone singleton = new Singletone();
// 懒汉式
private Singletone() {
}
// 保证返回一个实例
public static Singletone getSingleton() {
return singleton;
}
}
public class EHanShi {
public static void main(String[] args) {
Singletone singleton1 = Singletone.getSingleton();
Singletone singleton2 = Singletone.getSingleton();
System.out.println(singleton1==singleton2);
}
}
输出结果为: true
②懒汉单例(需要加双重检查锁来保证线程安全)
阐述: 所谓懒汉模式,就是像一个“懒汉”一样,需要用到创建实例了程序再去创建实例,不需要创建实例程序就“懒得”去创建实例。为什么说它不是线程安全的呢?因为在高并发的情况下懒汉单例就可能创建多个,这样不仅违背了单例的原则,也会在造成使用不同实例造成的线程安全问题,所以懒汉单例需要加锁。
// 懒汉单例 线程不安全 需要双重检查锁保证在JVM中只能有一个实例
class Singleton {
// 使用volatile禁止指令重排序
private static volatile Singleton singleton;
// 懒汉式
private Singleton() {
}
// 保证返回一个实例
public static Singleton getSingleton() {
if (singleton == null) { // 第一层锁
synchronized (Singleton.class) {
if (singleton == null) { //第二层锁
singleton = new Singleton();
}
}
}
return singleton;
}
}
public class LanHanShi {
public static void main(String[] args) {
Singleton s1 = Singleton.getSingleton();
Singleton s2 = Singleton.getSingleton();
System.out.println(s1 == s2);
}
}
输出结果为: true
懒汉式和饿汉式区别点: