1 基本概念
1、定义
- 保证一个类只有一个实例,并提供一个访问该实例的全局访问点。
2、使用场景
- Windows的任务管理器、回收站。
- 配置文件的读取类。
- 网站的计数器。
- 数据库连接池。
- ……
3、优点
4、实现方式
- 饿汉式(线程安全,调用效率高,不能延时加载)。
- 懒汉式(线程安全,调用效率不高,可以延时加载)。
- DCL懒汉式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)。
- 静态内部类式(饿汉式改进,线程安全,调用效率高,可以延时加载)。
- 枚举单例(线程安全,调用效率高,不能延时加载)。
2 实现方式
1 饿汉式
1、代码
package singleton;
/**
* 饿汉式
*/
public class Singleton01 {
// 1、私有化构造器
private Singleton01() {
}
// 2、类初始化时,立即加载该对象
private static Singleton01 instance = new Singleton01();
// 3、提供获取该对象的方法
public static Singleton01 getInstance() {
return instance;
}
}
2 懒汉式
1、代码
package singleton;
/**
* 懒汉式
*/
public class Singleton02 {
// 1、私有化构造器
private Singleton02() {
}
// 2、类初始化的时候,不立即加载该对象
private static Singleton02 instance;
// 3、提供获取该对象的方法,使用synchronized,效率较低
public static synchronized Singleton02 getInstance() {
if (instance == null) {
instance = new Singleton02();
}
return instance;
}
}
3 DCL懒汉式
1、代码
package singleton;
/**
* DCL懒汉式(双重检查锁)
*/
public class Singleton03 {
// 1、私有化构造器
private Singleton03() {
}
// 2、类初始化的时候,不立即加载该对象,volatile避免指令重排
private volatile static Singleton03 instance;
// 3、提供获取该对象的方法,效率提高了,但由于指令重排,可能出错
public static Singleton03 getInstance() {
if (instance == null) {
synchronized (Singleton03.class) {
if (instance == null) {
instance = new Singleton03();
}
}
}
return instance;
}
}
4 静态内部类
1、代码
package singleton;
import java.lang.reflect.Constructor;
/**
* 静态内部类
*/
public class Singleton04 {
private static boolean flag = false;
// 1、私有化构造器
private Singleton04() {
// 应对反射的方法:
if (!flag) {
flag = true;
} else {
throw new RuntimeException("不要试图用反射来破坏单例模式!");
}
}
// 2、静态内部类存放对象
private static class InnerClass {
private static final Singleton04 INSTANCE = new Singleton04();
}
// 3、提供获取该对象的方法
public static Singleton04 getInstance() {
return InnerClass.INSTANCE;
}
public static void main(String[] args) throws Exception {
// 反射会破坏该单例机制
Singleton04 instance01 = Singleton04.getInstance();
Constructor<Singleton04> declaredConstructor = Singleton04.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
Singleton04 instance02 = declaredConstructor.newInstance();
System.out.println(instance01 == instance02); // false
}
}
5 枚举
1、代码
package singleton;
public enum Singleton05 {
INSTANCE;
}