目录
1、什么是单例模式
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。
特点:
(1)一个类只有一个实例:构造器私有化
(2)该类必须自行创建这个实例:含有该类的静态变量保存这个唯一的实例
(3)该类必须自行向整个系统提供这个实例:对外提供获取该实例的方式:直接暴露或用get方法
2、如何用代码实现
2.1 饿汉式
饿汉式:直接创建对象,不存在线程安全问题
2.1.1 饿汉式1-直接实例化
public class Moon1 {
private Moon1(){}
public static final Moon1 INSTANCE = new Moon1();
}
public class SingleModel {
public static void main(String[] args) {
Moon1 moon1=Moon1.INSTANCE;
Moon1 moon11=Moon1.INSTANCE;
System.out.println(moon1==moon11); //true
}
}
2.1.2 饿汉式2-枚举实现
public enum Moon2 {
INSTANCE;
}
public class SingleModel {
public static void main(String[] args) {
Moon2 moon2=Moon2.INSTANCE;
Moon2 moon21=Moon2.INSTANCE;
System.out.println(moon2==moon21); //true
}
}
2.1.3 饿汉式3-静态代码块
public class Moon3 {
public static final Moon3 INSTANCE;
static {
INSTANCE=new Moon3();
}
private Moon3(){}
}
2.2 懒汉式
懒汉式:延迟创建对象,可能存在线程安全问题
2.2.1 懒汉式-单线程(多线程时线程不安全)
public class Moon4 {
private Moon4(){}
private static Moon4 instance;
public static Moon4 getInstance(){
if (instance==null){
instance=new Moon4();
}
return instance;
}
}
2.2.2 懒汉式-多线程(多线程时线程安全)
- 双重检查锁定
public class Moon5 {
private Moon5(){}
private static volatile Moon5 instance;
public static Moon5 getInstance(){
if(instance==null){//提高效率,如果已经有实例了,就不必再等待加锁
synchronized (Moon5.class){
if(instance==null){
instance=new Moon5();
}
}
}
return instance;
}
}
- 在getInstance方法上加同步
public class Moon6 {
private Moon6(){}
private static Moon6 instance;
public static synchronized Moon6 getInstance() {
if (instance == null) {
instance = new Moon6();
}
return instance;
}
}
- 静态内部类
比1、2更好,既实现了线程安全,又避免了同步带来的性能影响
主动使用内部类的变量导致内部类加载,类加载机制只会加载一次,所以线程安全
public class Moon7 {
private Moon7(){}
private static class Inner{
private static final Moon7 INSTANCE=new Moon7();
}
public static Moon7 getInstance(){
return Inner.INSTANCE;
}
}
参考文章:
添加链接描述