Java设计模式之单例模式

Java设计模式之单例模式,第1张

Java设计模式之单例模式

文章目录
  • Java设计模式之单例模式
  • 前言
  • 一、适用场景
  • 二、常见写法
    • 1.饿汉式单例
    • 2.懒汉式单例
      • 方式一
      • 方式二
      • 方式三
      • 方式四
    • 3.注册式单例
      • 枚举单例
      • 容器式单例
      • 反序列化单例
    • 4.ThreadLocal单例
  • 总结


前言
单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。隐藏其所有的构造方法。

一、适用场景

确保任何情况下都绝对只有一个实例。

比如:ServletContext、ServletConfig、ApplicationContext、DBPool

二、常见写法 1.饿汉式单例

饿汉式单例模式适用于单例对象比较少的情况。这样可以保证绝对线程安全、执行效率较高,所有对象类加载的时候就实例化。
代码:

public class HungrySingleton {
    private static final HungrySingleton instance = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return instance;
    }
}

优点:执行效率高、性能高、没有任何锁
缺点:某些情况下,可能会造成内存浪费

2.懒汉式单例 方式一

代码:

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
    }

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

优点:节省了内存
缺点:线程不安全

方式二

改造:通过synchronized关键字进行加锁

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
    }

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

优点:节省了内存,线程安全
缺点:性能低

方式三

改造:双重检查锁

public class LazySingleton {
    private volatile static LazySingleton instance; // volatile 防止指令重排序

    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                if (instance == null) {
                    instance = new LazySingleton();  // 会出现指令重排序
                }
            }
        }
        return instance;
    }
}

优点:性能高,线程安全
缺点:可读性差,不够优雅

方式四

代码:静态内部类

public class LazySingleton {
    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder {
        private static final LazySingleton INSTANCE = new LazySingleton();
    }
}

优点:写法优雅,利用了Java本身的语法特点,性能高,避免内存浪费
缺点:以上方式都能够被反射破环

3.注册式单例

将每一个实例都缓存到统一的容器中,使用唯一标识获取实例

枚举单例

代码:

public enum EnumSingleton {
    INSTANCE;

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}

优点:执行效率高、性能高,不能被反射破坏
缺点:某些情况下,可能会造成内存浪费

容器式单例

代码:

public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static final Map ioc = new ConcurrentHashMap<>();

    public static Object getInstance(String className) {
        if (ioc.containsKey(className)) {
            return ioc.get(className);
        }
        Object instance = null;
        try {
            instance = Class.forName(className).newInstance();
            ioc.put(className, instance);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instance;
    }
}
反序列化单例

代码:

public class SerializableSingleton implements Serializable {
    private static final SerializableSingleton INSTANCE = new SerializableSingleton();

    private SerializableSingleton() {
    }

    public static SerializableSingleton getInstance() {
        return INSTANCE;
    }

    private Object readResolve() {
        return INSTANCE;
    }
}
4.ThreadLocal单例

保证线程内部的全局唯一,且天生线程安全
代码:

public class ThreadLocalSingleton {
    private static final ThreadLocal INSTANCE = new ThreadLocal() {
        @Override
        protected ThreadLocalSingleton initialValue() {
            return new ThreadLocalSingleton();
        }
    };

    private ThreadLocalSingleton() {
    }

    public static ThreadLocalSingleton getInstance() {
        return INSTANCE.get();
    }
}

总结

单例模式的优点

在内存中只有一个实例,减少了内存开销。
可以避免对资源的多重占用。
设置全局访问点,严格控制访问。
单例模式的缺点
没有接口,扩展困难。
如果要扩展单例对象,只有修改代码,没有其他途径。

注意:

1,私有化构造器
2.保证线程安全
3.延迟加载
4.防止序列化和反序列化破坏单例
5.防止反射攻击单例

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/727570.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存