/** * 饿汉式 在类初始化时直接创建对象,不存在线程安全问题,不管你是否需要这个对象都会创建 * <p> * 1. 构造器私有化 * 2. 自行创建,并且用静态变量保存 * 3. 向外提供这个实例 * 4. 强调这是一个单例,我们可以用final修饰,不能改变引用,可以改变属性。 * * @author yuan */ public class Singleton1 { public static final Singleton1 INSTANCE = new Singleton1(); private static Date date = new Date(); private Singleton1() { } }
/** * 饿汉式 * <p> * 枚举类型:表示该类型的对象是有限的几个 * 我们可以限定成一个,就成了单例 * <p> * public enum Size{ SMALL, MEDIUM, LARGE, EXTRA_LARGE }; * 实际上,这个声明定义的类型是一个类,它刚好有四个实例,在此尽量不要构造新对象。 * https://www.cnblogs.com/liaojie970/p/6474733.html * * @author yuan */ public enum Singleton2 { /** * 相当于 Singleton2 INSTANCE = new Singleton2() * 反编译可以看到这个类的构造函数是私有的: private Singleton2() {} */ INSTANCE }
package com.yuan.middleware.base.design.single; import lombok.Data; import java.io.IOException; import java.util.Properties; /** * 饿汉式 * <p> * 静态代码块饿汉式,也是线程安全的 * 适合于需要灵活初始化属性 * * @author yuan */ @Data public class Singleton3 { public static final Singleton3 INSTANCE; private String info; static { Properties pro = new Properties(); try { //通过类加载器加载配置文件,需要特别注意文件路径否则NullPointerException pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties")); } catch (IOException e) { throw new RuntimeException(e); } INSTANCE = new Singleton3(pro.getProperty("info")); } private Singleton3(String info) { this.info = info; } }
package com.yuan.middleware.base.design.single; /** * 懒汉式 * 延迟创建这个实例对象 * 1. 构造器私有化 * 2. 用一个静态变量保存这个唯一的实例 * 3. 提供一个静态方法,获取这个实例对象 * * @author yuan */ public class Singleton4 { private static Singleton4 instance; private Singleton4() { } /** * 线程不安全 * * @return */ public static Singleton4 getInstance() { if (instance == null) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton4(); } return instance; } }
package com.yuan.middleware.base.design.single; /** * 懒汉式 * 延迟创建这个实例对象 * 1. 构造器私有化 * 2. 用一个静态变量保存这个唯一的实例 * 3. 提供一个静态方法,获取这个实例对象 * * @author yuan */ public class Singleton5 { private static Singleton5 instance; private Singleton5() { } /** * 线程安全 * * @return */ public static Singleton5 getInstance() { if (instance == null) { synchronized (instance) { if (instance == null) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton5(); } } } return instance; } }
package com.yuan.middleware.base.design.single; /** * 懒汉式 * 在内部类被加载和初始化时,才创建INSTANCE实例对象 * 静态内部类不会自动随着外部内的加载和初始化而初始化,它是需要单独去加载和初始化的 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的 * <p> * JVM必须确保一个类在初始化的过程中,如果是多线程需要同时初始化它,仅仅只能允许其中一个线程对其执行初始化操作, * 其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程。 * * @author yuan */ public class Singleton6 { private Singleton6() { } private static class Inner { private static final Singleton6 INSTANCE = new Singleton6(); } public static Singleton6 getInstance() { return Inner.INSTANCE; } }