Java单例模式的五种实现方式 懒汉式 饿汉式 双重校验锁 静态变量 静态内部类 枚举实现单例模式等

1、什么是单例模式?

Java单例模式是一种设计模式,用于确保一个类只有一个实例,并提供全局访问点以获取该实例。它通常用于需要共享资源或控制某些共享状态的情况下。

2、实现方式

懒汉式:在类加载的时候就创建对象,要再调用方法时才创建对象,减少内存开销。

饿汉式:再类加载的时候就实例化对象。

2.1 同步方法调用创建实例(懒汉式)

当刚加载这个类时不会直接初始化person,只有调用getPerson()方法时才会构建唯一实例。

java 复制代码
public class Person {
	private static Person person;
	//将构造器私有化,就无法从外部调用构造器构造对象
	private Person(){}
    
    //此时这个synchronized是保证线程安全
	public synchronized static Person getPerson() {
		if (person == null) {
			person = new Person();
		}
		return person;
	}
}

2.1 双重校验锁方式加载对象实例(懒汉式)

用两个判断,在第一个判断不通过时,我们不用同步代码块,直接返回结果

java 复制代码
public class Person {
	//此时要用volatile用于保证person = new Person()内部指令不排序
	private volatile static Person person;
	//将构造器私有化,就无法从外部调用构造器构造对象
	private Person(){}
 
	public  static Person getPerson() {
		if (person ==null){
			synchronized (Person.class){
				if (person == null){
					person = new Person();
				}
			}
		}
		return person;
	}
}

2.1 静态变量加载对象实例(饿汉式)

对象唯一实例会随着这个类的加载就会被初始化出来,基于 classloader 机制避免了多线程的同步问题,但它再还没有使用这个对象时就被加载出来,有点浪费内存空间。

java 复制代码
public class Person {
	private static Person person = new Person();
	//将构造器私有化,就无法从外部调用构造器构造对象
	private Person(){}
 
	public  static Person getPerson() {
		return person;
	}
}

2.1 静态内部类实现单例模式(懒汉式)

这里用到了一个知识点,就是内部类不会随着外部类的加载而加载,而是再第一次使用到内部类后再加载初始化内部类。这样的机制实现了懒汉模式。我们使用了final修饰,也将其确定为单例模式。

java 复制代码
public class Person {
	private static class PersonHolder {
		private static final Person INSTANCE = new Person();
	}
//将构造器私有化,就无法从外部调用构造器构造对象
	private Person (){}
	public static final Person getInstance() {
		return PersonHolder.INSTANCE;
	}
}

2.1 枚举实现单例模式(饿汉式)

这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

java 复制代码
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

完整的枚举单例

java 复制代码
public class User {
    //私有化构造函数
    private User(){ }
 
    //定义一个静态枚举类
    static enum SingletonEnum{
        //创建一个枚举对象,该对象天生为单例
        INSTANCE;
        private User user;
        //私有化枚举的构造函数
        private SingletonEnum(){
            user=new User();
        }
        public User getInstnce(){
            return user;
        }
    }
 
    //对外暴露一个获取User对象的静态方法
    public static User getInstance(){
        return SingletonEnum.INSTANCE.getInstnce();
    }
}

public class Test {
    public static void main(String [] args){
        System.out.println(User.getInstance());
        System.out.println(User.getInstance());
        System.out.println(User.getInstance()==User.getInstance());
    }
}
结果为true
相关推荐
Lin_Coder_10 分钟前
Python入门 — 类
开发语言·python
似水এ᭄往昔13 分钟前
【c语言】字符函数和字符串函数(1)
c语言·开发语言
laimaxgg26 分钟前
Qt常用控件之多行输入框QTextEdit
开发语言·c++·qt·qt5·qt6.3
楠枬35 分钟前
网页五子棋——项目测试
java·功能测试·spring
数据知道38 分钟前
python中httpx库的详细使用及案例
开发语言·爬虫·python·httpx
go546315846539 分钟前
基于Matlab实现汽车远近光灯识别的详细步骤及代码示例
开发语言·matlab·汽车
软件黑马王子1 小时前
C#初级教程(6)——函数:从基础到实践
开发语言·c#
患得患失9491 小时前
【前端】【面试】【树】JavaScript 树形结构与列表结构的灵活转换:`listToTree` 与 `treeToList` 函数详解
开发语言·前端·javascript·tree·listtotree·treetolist
胡图蛋.1 小时前
Spring MVC的执行流程步骤
java·spring
sevevty-seven1 小时前
spring MVC执行流程
java·开发语言·spring