Java 单例设计模式 常见4种

Java 单例设计模式 常见4种
适合功能场景
主要特色
饿汉式单例 Eager loading(当即加载方式)
懒汉式单例 Lazy Loading(延迟加载方式)
枚举单例
ConcurrentHashMap容器单例
适合功能场景
配置文件读写对象, 数据库链接池, Spring的 IOC容器 ApplicationContext, Windows的任务管理/回收站等
主要特色
单例类只能实例化一次
提供惟一全局访问入口来获取该实例
饿汉式单例 Eager loading(当即加载方式)
项目启动时类被加载, 对象与之同时实例化
除非项目重启否者对象不会有变化, 也就是线程安全的web

public class EagerSingleton implements Serializable {
    private static final long serialVersionUID = 7073777279565036708L;数据库

    private static volatile EagerSingleton instance = new EagerSingleton();设计模式

    /**
     * 为了防止经过反射机制实例化构造方法抛异常
      /
    private EagerSingleton() {
        if(instance != null){
            throw new RuntimeException("不容许被反射实例化");
        }
    }安全

    public static EagerSingleton getInstance() {
        return instance;
    }测试

    /**
     * readResolve方法的做用为防止序列化单例时破坏惟一实例的规则
      /
    private Object readResolve() throws ObjectStreamException {
        return instance;
    }this

}线程

public class App {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                System.out.println("EagerSingleton > " + Thread.currentThread().getName() + " > " + EagerSingleton.getInstance());
            });
            thread.start();
        }
    }设计

}对象

EagerSingleton > Thread-0 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-1 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-2 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-3 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-4 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-5 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-6 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-7 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-8 > com.test.web4.singleton.EagerSingleton@6a3289ca
EagerSingleton > Thread-9 > com.test.web4.singleton.EagerSingleton@6a3289caget

懒汉式单例 Lazy Loading(延迟加载方式)
类被加载时, 对象不被实例化. 此单例是经过类提供的全局访问入口来获取对象或实例化首个实例后获取对象
注: 懒汉式因为有线程安全问题必须作双重检查并加锁

public final class LazySingleton implements Serializable {
    private static final long serialVersionUID = -5683703520820349246L;

    private static volatile LazySingleton instance = null;

    /**
     * 为了防止经过反射机制实例化构造方法抛异常
      /
    private LazySingleton() {
        if (instance != null) {
            throw new RuntimeException("不容许被反射实例化");
        }
    }

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

    /**
     * readResolve方法的做用为防止序列化单例时破坏惟一实例的规则
      /
    private Object readResolve() throws ObjectStreamException {
        return instance;
    }

}

public class App {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                System.out.println("LazySingleton > " + Thread.currentThread().getName() + " > " + LazySingleton.getInstance());
            });
            thread.start();
        }
    }

}

LazySingleton > Thread-0 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-1 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-2 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-3 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-4 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-5 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-6 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-7 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-8 > com.test.web4.singleton.LazySingleton@5e5035fb
LazySingleton > Thread-9 > com.test.web4.singleton.LazySingleton@5e5035fb

枚举单例
Java虚拟机默认防止了枚举类型的序列化和反射破坏, 因此构造方法无需抛异常以及无需加 readResolve方法

public enum EnumSingleton {
    INSTENCE;

    private EnumSingleton() {}

    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTENCE;
    }

}

public class App {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                System.out.println("EnumSingleton > " + Thread.currentThread().getName() + " > " + EnumSingleton.getInstance());
            });
            thread.start();
        }
    }

}

EnumSingleton > Thread-0 > INSTENCE
EnumSingleton > Thread-1 > INSTENCE
EnumSingleton > Thread-2 > INSTENCE
EnumSingleton > Thread-3 > INSTENCE
EnumSingleton > Thread-4 > INSTENCE
EnumSingleton > Thread-5 > INSTENCE
EnumSingleton > Thread-6 > INSTENCE
EnumSingleton > Thread-7 > INSTENCE
EnumSingleton > Thread-8 > INSTENCE
EnumSingleton > Thread-9 > INSTENCE

ConcurrentHashMap容器单例
经过 ConcurrentHashMap管理多个对象, 虽然它自己是线程安全的但获取实例的方法不是, 因此须要使用同步锁

public class ContainerSingleton {
    private ContainerSingleton() {}

    private static Map<String,Object> ioc = new ConcurrentHashMap<>();

    public static Object getBean(final String className) {
        if (className != null && !"".equals(className)) {
            synchronized (className) {
                if (ioc.containsKey(className)) {
                    return ioc.get(className);
                }
                Object obj = null;
                try {
                    obj = Class.forName(className).newInstance();
                    ioc.put(className,obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return obj;
            }
        }
        return null;
    }

}

/**

  • 此测试类需经过反射机制实例化, 因此必须有无参构造方法
  • */

public class TestA {
    private Integer id;
    private String name;

    public TestA() {}

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class App {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                System.out.println("ContainerSingleton > " + Thread.currentThread().getName() +
                        " > " + ContainerSingleton.getBean("com.test.web4.singleton.TestA"));
            });
            thread.start();
        }
    }

}

ContainerSingleton > Thread-0 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-1 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-2 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-3 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-4 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-5 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-6 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-7 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-8 > com.test.web4.singleton.TestA@6d559005ContainerSingleton > Thread-9 > com.test.web4.singleton.TestA@6d559005

相关文章
相关标签/搜索