单例模式,顾名思义 一个类只存在一个实例A,不同客户端都复用同一个实例。 如JavaBean默认是单例,生成后存在HashMap中,JavaBean大部分都是无状态的,可比拟成一个工具类,无修改故安全。单例模式在Java中有多种实现。单例模式可能在面试中手撕
设计模式,一定要敲代码理解
饿汉式(线程不安全/安全)
java
/**
* @author ggbond
* @date 2024年04月03日 07:56
* 饿汉式
*/
public class Singleton00 {
private static Singleton00 instance;
//构造私有,外部不能通过new,获取实例
private Singleton00(){};
//线程不安全
public static Singleton00 getInstance(){
if(null==instance) {
instance=new Singleton00();
}
return instance;
}
//线程安全
public static synchronized Singleton00 getInstance1(){
if(null==instance) {
instance=new Singleton00();
}
return instance;
}
}
懒汉式(线程安全)
java
/**
* @author ggbond
* @date 2024年04月03日 07:47
* 懒汉式 线程安全
*/
public class Singleton01 {
//类加载时初始化
private final static Singleton01 instance=new Singleton01();
private Singleton01(){};
public static Singleton01 getInstance(){
return instance;
}
}
双重锁DCL (线程安全)
java
/**
* @author ggbond
* @date 2024年04月03日 07:49
* DCL 线程安全
*/
public class Singleton02 {
private volatile static Singleton02 instance;
private Singleton02(){};
public Singleton02 getInstance(){
if (instance!=null){ //防止 已有对象,还在加锁后判断。目的减少性能损耗
return instance;
}else {
synchronized(Singleton02.class) {//A与B同时到这里,A拿锁进去,B在这里等待。
if (instance==null){ // 这里判断的原因,是A new完对象后,防止B进来又new一次。
instance=new Singleton02();
}
}
return instance;
}
}
}
类的内部类(线程安全)
java
/**
* @author ggbond
* @date 2024年04月03日 07:53
* 类的内部类 线程安全 JVM保证访问安全,一个类的构造方法在多线程环境下能被正确地加载
*/
public class Singleton03 {
private static class Singleton {
private static Singleton03 instance=new Singleton03();
}
private Singleton03(){};
public static Singleton03 getInstance(){
return Singleton.instance;
}
}
枚举单例(线程安全)
java
/**
* @author ggbond
* @date 2024年04月03日 08:24
*/
public enum Singleton04 {
INSTANCE;
public void test(){
System.out.println("枚举单例");
}
}
测试 枚举是单例还是原型
java
public class test_singleton04 {
public static void main(String[] args) {
Singleton04 s1=Singleton04.INSTANCE;
Singleton04 s2=Singleton04.INSTANCE;
System.out.println(s1==s2); //true
}
}
结果
java
true
总结
一个类不能反复的new实例,单例模式体现对象资源复用思想,不满足单一职责原则。多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。