单例模式

242 阅读2分钟

前言

单例模式是在编程中常用的一种设计模式,确保某个类只能存在一个对象实例,并供全局调用

单例模式创建

懒汉式

public class HelloService {

    private static HelloService instance;

    private HelloService() {
    }

    public static HelloService getInstance() {
        if (instance == null) {
            instance = new HelloService();
        }
        return instance;
    }
}

懒汉式创建的单例模式线程不安全,在并发下,可能会导致创建了多个实例

保证线程安全的话,加锁就好了

public class HelloService {

    private static HelloService instance;

    private HelloService() {
    }

    public static synchronized HelloService getInstance() {
        if (instance == null) {
            instance = new HelloService();
        }
        return instance;
    }
}

饿汉式

public class HelloService1 {

    private static HelloService1 instance = new HelloService1();

    private HelloService1() {
    }

    public static synchronized HelloService1 getInstance() {
        return instance;
    }
}

饿汉式是线程安全的

静态内部类

public class HelloService2 {


    private HelloService2() {
    }

    public static class Hello {

        private static HelloService2 instance = new HelloService2();
    }

    public static synchronized HelloService2 getInstance() {
        return Hello.instance;
    }
}

这种也是线程安全的,静态内部类的优点在于,外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存,只有当调用getInstance()方法才会加载

双重锁模式

public class HelloService3 {


    private static HelloService3 instance;

    private HelloService3() {
    }

    public static synchronized HelloService3 getInstance() {
        if(instance == null) { //判断是否实例化
            synchronized (HelloService3.class) {
                if(instance == null) {
                    instance = new HelloService3();
                }
            }
        }
        return instance;
    }
}

但这种也是可能造成线程不安全的,需要用到关键字volatile,防止指令重排,是线程安全

public class HelloService3 {


    private volatile static HelloService3 instance;

    private HelloService3() {
    }

    public static synchronized HelloService3 getInstance() {
        if(instance == null) { //判断是否实例化
            synchronized (HelloService3.class) {
                if(instance == null) {
                    instance = new HelloService3();
                }
            }
        }
        return instance;
    }
}

单例模式注意

单例模式,克隆可破坏、反射可破坏、序列化可破坏等 如克隆

@Data
public class User implements Cloneable {

    private Long id;

    private String name;


    public User clone() throws CloneNotSupportedException {
        return (User) super.clone();
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        User user = new User();
        User user1 = user.clone();
        System.out.println(user);
        System.out.println(user1);
    }
}

输出结果为

image.png

总结

使用单例模式可以不用频繁的在系统中创建对象,节省了系统资源,使用单例模式可以提高系统性能

1714232860866.jpg