设计模式笔记 -- 单例模式

单例模式有五种写法,分别是

饿汉式

懒汉式

双重检查

静态内部类

枚举

但是饿汉式又分两种静态常量静态代码块,懒汉式又分三种线程不安全的,线程安全(同步方法),线程安全(同步代码块),所以细分下来一共有八种写法。

1,饿汉式(静态常量)

实现原理是通过一个静态方法返回一个静态实例,代码如下

public class Singleton {
    private Singleton(){}

    private final static Singleton singleton = new Singleton();

    public static Singleton getInstance(){
        return singleton;
    }
}

优点:写法简单,在类加载的时候完成实例化,避免了线程同步问题

缺点:在类加载的时候就完成实例化,如果一直没有用的这个类,就造成了内存的浪费

2,饿汉式(静态代码块)

public class Singleton {
    private Singleton(){}

    private static Singleton singleton;
    
    static {
        singleton = new Singleton();
    }

    public static Singleton getInstance(){
        return singleton;
    }
}

这种方法跟上面静态常量写法的优缺点是一样的

3,懒汉式(线程不安全)

public class Singleton {
    private Singleton(){}

    private static Singleton singleton;

    public static Singleton getInstance(){
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

优点:不会在你不用的情况下去创建对象

缺点:只能在单线程下使用,多线程情况下if语句中可能多个线程进入,就会创建多个对象

在实际开发中不建议使用

4,懒汉式(线程安全,同步方法)

在上面代码的基础上加一个synchronize关键字

public class Singleton {
    private Singleton(){}

    private static Singleton singleton;

    public static synchronized Singleton getInstance(){
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

优点:解决了线程不安全的问题

缺点:效率太低了,每个线程获取实例的时候,执行getInstance方法都要进行同步

在实际开发中,不推荐使用

5,懒汉式(线程安全,同步代码块)

开起来线程安全,其实还是线程不安全的,依旧会可能又两个线程进入if语句中

public class Singleton {
    private Singleton(){}

    private static Singleton singleton;

    public static Singleton getInstance(){
        if(singleton == null){
            
            synchronized (Singleton.class){
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

实际开发中,不能使用这种方式

6,双重检查

public class Singleton {
    private Singleton(){}

    private static volatile Singleton singleton;

    public static Singleton getInstance(){
        if(singleton == null){

            synchronized (Singleton.class){
                
                if(singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

使用volatile关键字保证可见性和有序性,在同步块外面和里面都进行一次判断,解决了线程安全问题,也解决了懒加载问题

7,静态内部类

采用类加载的机制来保证初始化实例时只有一个线程

静态内部类在Singleton被装载时不会实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类

类的静态属性只会在第一次加载类的时候初始化,JVM帮我们保证了线程的安全,在类初始化时,别的线程是无法进入的

public class Singleton {
    private Singleton(){}

    private static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

优点:保证了线程安全,利用静态内部类的特点实现了懒加载,效率高

8,枚举

enum SingletonEnum{
    INSTANCE;
}

优点:借助jdk1.5中添加的枚举来实现单例模式。不仅能避免多线程同步的问题,还能防止反序列化重新创建对象 

 

在jdk中哪个地方用到了单例模式呢,RunTime类使用饿汉式实现单例模式

Guess you like

Origin blog.csdn.net/qq_41890624/article/details/118034660