单例模式设计
1、饿汉式
/** * 饿汉式:直接创建对象,不管你是否需要,都会创建这个对象; * * 1、构造器私有化 * 2、自动创建,并且用静态保存 * 3、向外提供这个实例 * 4、强调这是一个单利模式,可以用final修饰 */ public class Singleton1 { private Singleton1(){ } public static final Singleton1 INSTANCE = new Singleton1(); }
2、枚举
/** * 枚举类型:表示该类型的对象是有限的几个, * 我们定义成一个,就成了单利模式 */ public enum Singleton2 { INSTANCE }
3、适用于初始化比较复杂的实例
/** * 适用于初始化比较复杂的实例; */ public class Singleton3 { public static final Singleton3 INSTANCE; private Singleton3(){ } static { //此处初始化其他数据; INSTANCE = new Singleton3(); } }
4、懒汉式
/** * 懒汉式:延迟创建这个实例对象; * * 1、构造器私有化 * 2、用一个静态变量保存这个唯一的实例; * 3、提供一个静态方法,获取这个实例; */ public class Singleton4 { private static Singleton4 instance; private Singleton4(){ } public static Singleton4 getInstance(){ if (instance == null){ //Thread.sleep(100);此处睡眠,若两个线程同时进入,会创建两个对象 instance = new Singleton4(); } return instance; } }
/** * 懒汉式:延迟创建这个实例对象; * * 1、构造器私有化 * 2、用一个静态变量保存这个唯一的实例; * 3、提供一个静态方法,获取这个实例; */ public class Singleton5 { private static Singleton5 instance; private Singleton5(){ } public static Singleton5 getInstance(){ synchronized (Singleton5.class){ if (instance == null){ try { //此处睡眠,若两个线程同时进入,会创建两个对象 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton5(); } } return instance; } }
5、内部类的方式
//在内部类加载的时候才会创建对象INSTANCE //静态内部类不会自动随着外部类的加载和初始化而初始化,他是单独去加载和初始化的; public class Singleton6 { private Singleton6(){ } private static class Inner{//内部类 private static final Singleton6 INSTANCE = new Singleton6(); } public static Singleton6 getInstance(){ return Inner.INSTANCE; } }
6、双端检索机制(DCL)
public class SingletonDemo2 { public static volatile SingletonDemo2 instance = null; private SingletonDemo2(){ System.out.println("SingletonDemo2"); } //DCL(双端检索机制) public static SingletonDemo2 getInstance(){//由于指令重排机制,不一定100%线程安全 if (instance == null){ synchronized (SingletonDemo2.class){ if (instance == null){ instance = new SingletonDemo2(); } } } return instance; } public static void main(String[] args) { for (int i = 0; i < 1000; i++) { new Thread(() ->{ getInstance(); },String.valueOf(i)).start(); } } }