单例模式
饿汉式
-
静态常量
- 构造器私有化
- 类的内部创建对象
- 向外暴露一个静态的公共方法
class Singleton { // 构造器私有化,防止外部new private Singleton() { } // 本类内部创建对象实例 private final static Singleton instance = new Singleton(); // 提供一个共有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
优点:避免了线程同步问题
缺点:没有懒加载的效果,如果未使用当前实例,造成内存的浪费
-
静态代码块
class Singleton { // 构造器私有化,防止外部new private Singleton() { } // 本类内部创建对象实例 private final static Singleton instance; // 在静态代码块中,创建单例对象 static { instance = new Singleton(); } // 提供一个共有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
优点:避免线程同步
缺点:内存浪费
懒汉式
-
懒汉式(线程不安全)
class Singleton { private static Singleton instance; private Singleton() {} // 提供一个静态的公有方法,使用到方法,才创建实例 public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
优点:单线程,懒加载
缺点:线程不安全(多个线程同步进入判断就会创建多个实例),不建议使用这种方式
-
懒汉式(线程安全,同步方法)
class Singleton { private static Singleton instance; private Singleton() {} // 提供一个静态的公有方法,加入同步处理的代码,解决线程暗器问题 public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
优点:解决线程安全问题
缺点:效率太低,不推荐使用
-
懒汉式(线程安全,同步代码块)
class Singleton { private static Singleton instance; private Singleton() {} // 提供一个静态的公有方法,加入同步处理的代码,解决线程暗器问题 public static synchronized Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { instance = new Singleton(); } } return instance; } }
不能保证同步,不能使用这个方法
-
双重检查
class Singleton { private static volatile Singleton instance; private Singleton() {} // 加入双重检查,解决线程安全,解决懒加载 public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { instance = new Singleton(); } } return instance; } }
优点:两次null检查,保证了线程安全,后续的判断无需进行同步代码块判断,提升了效率
推荐使用这种方法
-
静态内部类
class Singleton { // 构造器私有化 private Singleton(){} // 静态内部类使用静态属性 private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } // 提供静态的公有方法,直接返回静态变量 public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
优点:避免线程安全,利用静态内部类特点实现延迟加载,效率高,推荐使用
-
枚举
enum Singleton { INSTANCE; public void sayOk() { System.out.println("ok"); } }
优点:避免多线程同步且防止反序列化重新创建对象的问题,推荐使用
注意事项
- 单例模式保证只存在一个对象,节省系统资源,对于需要频繁创建销毁的对象,使用单例模式提高性能
- 获取对象需要使用方法获取,而不是new
- 使用场景:重量级对象,经常使用到的对象,工具类对象,频繁访问数据库或者文件的对象(数据源,session工厂)----java.lang.Runtime