Java进阶之单例模式
- Java进阶之单例模式
单例模式 singleton
- 永远都是一个对象
懒汉式
- 在多线程下是非线程安全
- 单例模式的懒汉式体现了缓存的思想,延时加载就是一开始不要加载资源或者数据,一直 等,等到马上就要使用这个资源的或者数据时才去加载。
- 懒汉式是定性的时间换空间,不加同步的懒汉式是线程不安全的
public class Singleton1 { private static Singleton1 singleton = null; private Singleton1(){ } public static Singleton1 getInstance(){ //判断内存中是否对singleton对象实例化,如果有,就给予当前实例化,如果没有,则new一个 synchronized (Singleton1.class){ if(singleton == null){ singleton = new Singleton1(); } } return singleton; } //两个类,放一起了,我懒 public static void main(String[] args) { Singleton1 s1 = Singleton1.getInstance(); Singleton1 s2 = Singleton1.getInstance(); System.out.println(s1 == s2); } }
饿汉式
- 饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管用不用,先创建出来,然后每次调用的时候,就不需要判断了,节省了运行时间。
- 饿汉式在多线程模式下默认是线程安全的
- 将对象使用final,防止对象被改变
- 可以将整个方法加锁,防止线程不安全
public class Singleton2 { private static final Singleton2 singleton2 = new Singleton2(); private Singleton2(){ } public synchronized static Singleton2 singleton2(){ return singleton2; } //两个类,放一起了,我懒 public static void main(String[] args) { Singleton2 s3 = Singleton2.singleton2(); Singleton2 s4 = Singleton2.singleton2(); System.out.println(s3 ==s4); } }
使用静态内部类实现单例模式
- 当getInstance方法第一次被调用,第一次读取SingletonHolder.instance,导致SingletonHolder类初始化
- 类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例
- 由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性
public class Singleton { private static class SingletonHoler { /** * 静态初始化器,由JVM来保证线程安全 */ private static Singleton instance = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return SingletonHoler.instance; } public static void main(String[] args) { Singleton s3 = Singleton.singleton2(); Singleton s4 = Singleton.singleton2(); System.out.println(s3 ==s4); } }
使用枚举来实现单例
- 枚举实现单例是最为推荐的一种方法,因为它更简洁并且就算通过序列化,反射等也没办法破坏单例性
- Java枚举类型的基本思想:通过公有的静态final域为每个枚举常量导出实例的类
- 从某个角度讲,枚举是单例的泛型化,本质上是单元素的枚举
public enum EnumSingle { INSTANCE; public EnumSingle getInstance() { return INSTANCE; } }