Java设计模式之单例模式的六种写法

本文介绍了单例模式的六种写法:

  • 饿汉式

  • 懒汉式(线程不安全)

  • 懒汉式(上锁,线程安全)

  • 懒汉式(双重校验锁,线程安全)

  • 静态内部类(线程安全)

  • 枚举(线程安全)

talk is cheap,show you the code:

饿汉式

package com.cc.singleton;

/**
 * 单例模式:饿汉式
 * 优点:类加载时就实例化完成,线程安全
 * 缺点:可能永远都不会被执行到,造成资源浪费
 * @author cc
 * @date 2021-12-14 15:30
 */
public class Singleton01 {
    private static final Singleton01 INSTANCE = new Singleton01();

    private Singleton01() {}

    public static Singleton01 getInstance() {
        return INSTANCE;
    }

    public static void main(String[] args) {
        // 模拟多线程环境下对单例的访问,一个合格的单例应该能保证hashCode()是一致的
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton01.getInstance().hashCode());
            }).start();
        }
    }
}
复制代码

懒汉式(线程不安全)

package com.cc.singleton;

/**
 * 单例模式:懒汉式(线程不安全)
 * 优点:调用时才进行实例化,资源利用率高
 * 缺点:线程不安全
 * @author cc
 * @date 2021-12-14 15:30
 */
public class Singleton02 {
    private static Singleton02 INSTANCE;

    private Singleton02() {}

    public static Singleton02 getInstance() {
        if (INSTANCE == null) {
            // 这里模拟实例化耗时来演示懒汉式单例线程不安全
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Singleton02();
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton02.getInstance().hashCode());
            }).start();
        }
    }
}
复制代码

懒汉式(上锁,线程安全)

package com.cc.singleton;

/**
 * 单例模式:懒汉式(上锁,线程安全)
 * 优点:调用时才进行实例化,资源利用率高
 * 缺点:每次调用都要上锁,影响性能
 * @author cc
 * @date 2021-12-14 15:30
 */
public class Singleton03 {
    private static Singleton03 INSTANCE;

    private Singleton03() {}

    public static synchronized Singleton03 getInstance() {
        if (INSTANCE == null) {
            // 这里模拟实例化耗时
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Singleton03();
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton03.getInstance().hashCode());
            }).start();
        }
    }
}
复制代码

懒汉式(双重校验锁,线程安全)

package com.cc.singleton;

/**
 * 单例模式:懒汉式(双重校验锁,线程安全)
 * 优点:调用时才进行实例化,资源利用率高
 * @author cc
 * @date 2021-12-14 15:30
 */
public class Singleton04 {
    // valatile共享锁可以保证类属性对所有线程可见
    private static volatile Singleton04 INSTANCE;

    private Singleton04() {}

    public static Singleton04 getInstance() {
        /**
         * 双重校验锁
         * 第一次校验不加锁,第二次校验加锁
         * 这样单例只会在实例化的时候上锁,实例化后就不会了
         */
        if (INSTANCE == null) {
            // 这里模拟实例化耗时
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (Singleton04.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton04();
                }
            }
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton04.getInstance().hashCode());
            }).start();
        }
    }
}
复制代码

静态内部类(线程安全)

package com.cc.singleton;

/**
 * 单例模式:静态内部类(线程安全)
 * 优点:既能保证懒加载,又能保证线程安全
 * 这种写法使用JVM的机制保证了线程安全问题
 * @author cc
 * @date 2021-12-14 15:30
 */
public class Singleton05 {

    private static class Singleton05Holder {
        private static final Singleton05 INSTANCE = new Singleton05();
    }

    private Singleton05() {}

    public static final Singleton05 getInstance() {
        return Singleton05Holder.INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton05.getInstance().hashCode());
            }).start();
        }
    }
}
复制代码

枚举(线程安全)

package com.cc.singleton;

/**
 * 单例模式:枚举(线程安全)
 * 优点:写法优雅,线程安全,还能防止反序列化
 * @author cc
 * @date 2021-12-14 15:30
 */
public enum Singleton06 {

    INSTANCE;

    public static Singleton06 getInstance() {
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton06.getInstance().hashCode());
            }).start();
        }
    }
}
复制代码

猜你喜欢

转载自juejin.im/post/7041473990233161741