单例模式
饥汉模式:类加载的时候,就实例化了。
懒汉模式:类加载的时候,没有实例化,当使用的时候才实例化。
总结:1,构造方法的修饰符是需要是private,避免别人new或者自己new而导致不是单例的。所以不能用默认的 2,图2线程是不安全的。并发时,两个线程可能同时进入到 if(instance == null)这段代码处,此时,instance为null。两个线程可能分别生成一个实例。导致不是单例。 3,图3是线程安全的单例模式(推荐使用)。之所以说是双重检查,是因为判空语句有两条。如果去掉第一个判空语句,那么每次调用getInstance()这个方法时,都会进入同步代码块,影响效率。如果去掉第二个判空语句那么就可能出现和图2一样的冲突情况。 4,注意静态变量instance是用volatile修饰的。是因为instance = new ....这段代码并非是一个原子操作。实际上,这段代码在jvm中大概做了3件事 4.1 给instance分配内存 4.2 调用构造方法实例化成员变量 4.3 将实例化的对象,指向分配的内存(到这一步instance就是非null了)
而这3步在jvm中有可能按照1,3,2执行。如果是这样,可能导致3执行完毕,2未执行之前,被线程二抢占了。这样线程2会认为instance不为null,直接返回,并且使用。但其实instance还没有实例化(2未执行)。当然并发情况才可能出现这种情况。如果只有一个线程的话123还是132的执行方式没有多大关系,因为这这三都是要执行的。