单例模式是 Java 中最简单的设计模式之一,它是指一个类在运行期间始终只有一个实例,我们就把它称之为单例模式。
实现方式
一、饿汉模式
public class Singleton {
// 声明私有对象
private static Singleton instance = new Singleton();
// 获取实例(单例对象)
public static Singleton getInstance() {
return instance;
}
private Singleton() {
}
// 方法
public void sayHi() {
System.out.println("Hi,Java.");
}
}
class SingletonTest {
public static void main(String[] args) {
// 调用单例对象
Singleton singleton = Singleton.getInstance();
// 调用方法
singleton.sayHi();
}
}
优点
线程安全
缺点
加载后就会创建实例,一直不是用就会造成浪费
二、懒汉模式
public class Singleton {
// 声明私有对象
private static Singleton instance;
// 获取实例(单例对象)
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
private Singleton() {
}
// 方法
public void sayHi() {
System.out.println("Hi,Java.");
}
}
class SingletonTest {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
singleton.sayHi();
}
}
优点
不会造成资源的浪费,在调用的时候才会创建被实例化对象
缺点
多线程环境下是非线程是安全的,比如多个线程同时执行到 if 判断处,此时判断结果都是未被初始化,那么这些线程就会同时创建 n 个实例,这样就会导致意外的情况发生
三、双重检测锁
public class Singleton {
// 声明私有对象 通过volatile修饰,对其他线程可见
private volatile static Singleton instance;
// 获取实例(单例对象)
public static Singleton getInstance() {
// 第一次判断
if (instance == null) {
synchronized (Singleton.class) {
// 第二次判断
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
private Singleton() {
}
// 类方法
public void sayHi() {
System.out.println("Hi,Java.");
}
}
四、静态内部类
public class Singleton {
// 静态内部类
private static class SingletonInstance {
private static final Singleton instance = new Singleton();
}
// 获取实例(单例对象)
public static Singleton getInstance() {
return SingletonInstance.instance;
}
private Singleton() {
}
// 类方法
public void sayHi() {
System.out.println("Hi,Java.");
}
}
实现原理
当初始化实例时只有一个线程执行
五、枚举方式
public class Singleton {
// 枚举类型是线程安全的,并且只会装载一次
private enum SingletonEnum {
INSTANCE;
// 声明单例对象
private final Singleton instance;
// 实例化
SingletonEnum() {
instance = new Singleton();
}
private Singleton getInstance() {
return instance;
}
}
// 获取实例(单例对象)
public static Singleton getInstance() {
return SingletonEnum.INSTANCE.getInstance();
}
private Singleton() {
}
// 类方法
public void sayHi() {
System.out.println("Hi,Java.");
}
}
class SingletonTest {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
singleton.sayHi();
}
}