01单例模式
单例模式写法常规的有7-8种吧,但是有部分写法是不太严谨的,在多线程当中,有可能会造成线程安全的问题,推荐三种比较完美的写法。
写法一
饿汉式(基于classloder机制避免了多线程的同步问题
/**
* 1、利用JVM保证一个类只加载一次来保证创建对象的唯一性。加载类时会进行静态变量初始化。
* 2、私有化构造方法
*/
public class Singleton01 {
private static final Singleton01 INSTANCE = new Singleton01();
private Singleton01(){}
public static Singleton01 getInstance(){
return INSTANCE;
}
public static void main(String[] args) {
for(int i = 0; i<100; i++) {
//测试在高并发时,返回的对象是否一致
new Thread(() -> System.out.println(INSTANCE.hashCode())).start();
}
}
}
写法二
利用静态内部类来实现更安全的机制(静态内部类需要用到时才会加载,对饿汉式有一些改进)
public class Singleton02 {
private static class Holder {
private static final Singleton02 INSTANCE = new Singleton02();
}
private Singleton02(){}
public static Singleton02 getInstance(){
return Holder.INSTANCE;
}
public static void main(String[] args) {
for(int i = 0; i<100; i++) {
//测试在高并发时,返回的对象是否一致
new Thread(() -> System.out.println(getInstance().hashCode())).start();
}
}
}
写法三
利用枚举类型,最简洁高效(避免反射、序列化问题)
避免反射:可能通过反射调用类的构造方法,进行创建对象。但反射在通过newInstance创建对象时,会检查该类是否ENUM修饰,如果是则抛出异常,反射失败。
序列化问题:任何一个readObject方法,不管是显式的还是默认的,它都会返回一个新建的实例,这个新建的实例不同于该类初始化时创建的实例。
public enum Singleton03 {
INSTANCE;
public String other() {
return "Hello World.";
}
public static void main(String[] args) {
for(int i = 0; i<100; i++) {
//测试在高并发时,返回的对象是否一致
new Thread(() -> System.out.println(INSTANCE.hashCode())).start();
}
}
}
以上是 01单例模式 的全部内容, 来源链接: utcz.com/z/518929.html