标签:序列 构造器 pre instance jvm win for java 基础
1.饿汉式
类加载到内存后,就实例化一个单例,jvm保证线程安全 推荐使用
缺点:不管用到与否,类加载时就会完成实例化 (类加载static修饰的就会执行)
额外知识点(一般对象)
//使用反射的方式 也叫做通过反序列化的方式获取对象 Class clazz=Class.forName("") //这时候只会类加载把class放入内存 clazz.newInstance(); //这时候才实例化 //一般创建对象 new Object() //使用构造器创建对象,类加载并实例化
public class Singleton1 { private static final Singleton1 singleton1=new Singleton1(); private Singleton1() {} public Singleton1 getInstance(){ return singleton1; } }
2.懒汉式
优化了饿汉式,达到了按需初始化的目的。但是多线程时会带来线程不安全问题
public class Singleton2 { private static Singleton2 singleton2; private Singleton2() { } public Singleton2 getInstance(){ if(singleton2==null){ singleton2=new Singleton2(); } return singleton2; }
线程1获取对象时,当执行到if语句时,判断对象为空,但是还没有执行构造器,这时候线程2也执行if语句。线程1与线程2都执行了构造器,所以获取到的对象不是同一个,即不是单例
3.懒汉式(线程安全版)
public class Singleton3 { private static volatile Singleton3 singleton3; private Singleton3() { } public Singleton3 getInstance(){ if(singleton3==null){ synchronized(this){ if(singleton3==null) { singleton3 = new Singleton3(); } } } return singleton3; } }
第一个if的作用是 节省代码执行的时间
第二个if的作用 保证此线程操作时其他线程没有改变其值,保证其原子性
volatile的作用 java虚拟机内部执行的时候对于Java汇编语言进行优化,语句重排。 如果不加, 没有初始化的时候就返回singleton3,导致无法单例。
4.枚举的方式
目前最完美的写法,不仅可以解决线程同步,而且还能防止反序列化。 但是不太推荐使用
public enum Singleton4 { INSTANCE; }
标签:序列 构造器 pre instance jvm win for java 基础
原文地址:https://www.cnblogs.com/zxj-study/p/13161933.html