7

了解23种设计模式-单例模式

 3 years ago
source link: https://blog.lacia.cn/2019/11/05/%E4%BA%86%E8%A7%A323%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

了解23种设计模式-单例模式

  • 饿汉式
    public class Mgr01 {
    private static final Mgr01 INSTANCE = new Mgr01();
    private Mgr01(){}
    private static Mgr01 getInstance(){return INSTANCE;}
    public void m(){
    System.out.println("m");
    }
    public static void main(String[] args) {
    Mgr01 m1 = Mgr01.getInstance();
    Mgr01 m2 = Mgr01.getInstance();
    System.out.println(m1 == m2);
    }
    }

    类加载到内存后就实例化一个单例 , JVM 保证线程安全
    缺点: 不管是否用到,类装载时就完成实例化 (通常问题不大,写法简单)

  • 懒汉式
    public class Mgr02 {
    private volatile static Mgr02 INSTANCE;
    private Mgr02(){};
    /**
    * 可以使用线程锁的方式(synchronized 修饰此方法)解决,但是性能会下降
    * @return
    */
    public static Mgr02 getInstance(){
    if (INSTANCE == null) {
    // 或者在此处加锁,解决线程安全问题
    synchronized (Mgr02.class){
    if (INSTANCE == null ){
    INSTANCE = new Mgr02();
    }
    }
    }
    return INSTANCE;
    }
    public void m(){
    System.out.println("m");
    }

    public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
    new Thread(()->{
    // 同一个类的 不同对象,它的 hashCode 是不同的
    System.out.println(Mgr02.getInstance().hashCode());
    }).start();
    }
    }
    }

    为了保证线程安全,写法相对饿汉式麻烦,但是只有在使用时才会实例化

  • 静态内部类
    public class Mgr03 {
    private Mgr03(){}
    private static class Mgr03Holder {
    private static final Mgr03 INSTANCE = new Mgr03();
    }
    public static Mgr03 getInstance() {
    return Mgr03Holder.INSTANCE;
    }
    public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
    new Thread(()->{
    // 同一个类的 不同对象,它的 hashCode 是不同的
    System.out.println(Mgr03.getInstance().hashCode());
    }).start();
    }
    }
    }

    与饿汉式类似,都是由 JVM 保证线程安全,但静态内部类是延迟加载

  • 枚举
    public enum  Mgr04 {
    //枚举单例
    INSTANCE;
    public void m(){
    System.out.println("m");
    }
    public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
    new Thread(()->{
    // 同一个类的 不同对象,它的 hashCode 是不同的
    System.out.println(Mgr04.INSTANCE.hashCode());
    }).start();
    }
    }
    }

    枚举单例,解决线程同步,解决反序列化(不能通过反射拿到多个实例,枚举没有构造方法)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK