单例模式
单例模式是指,在整个jvm生命周期中,让一个类只有一个实例存在,类只实例化一次。所有的代码共享这一个实例。
单实例创建-饿汉模式
利用jvm在加载类时,线程安全的,保证类加载完毕,实例创建完毕,只创建一次
public class VillianSingletonTest {
private VillianSingletonTest() {
}
private static final VillianSingletonTest INSTANCE = new VillianSingletonTest();
public static VillianSingletonTest getInstance() {
return INSTANCE;
}
}
单实例创建-多种创建方法比较
private static MultiSingletonCreateTest INSTANCE;
private MultiSingletonCreateTest() {
}
public static void main(String[] args) {
}
/**实例1,存在问题:线程不安全,不能保证整个jvm中只有DclLockTest一个实例,
* 还有半初始化问题,
* 比如两个线程同时执行:INSTANCE = new DclLockTest();这行代码
*/
public static MultiSingletonCreateTest getInstance1() {
if (INSTANCE == null) {
//其他逻辑
INSTANCE = new MultiSingletonCreateTest();
//其他逻辑
return INSTANCE;
}
return INSTANCE;
}
/**实例2,存在问题:虽然能够保证线程安全,但是影响程序并发度,损失性能
*
*/
public static synchronized MultiSingletonCreateTest getInstance2() {
if (INSTANCE == null) {
INSTANCE = new MultiSingletonCreateTest();
return INSTANCE;
}
return INSTANCE;
}
/**实例3,存在问题:虽然不会同时创建实例,但是还是会重复创建实例,
* 如两个线程同时加锁,后加锁成功的线程,也会创建实例
*
*/
public static MultiSingletonCreateTest getInstance3() {
if (INSTANCE == null) {
synchronized(DclLockTest.class){
INSTANCE = new MultiSingletonCreateTest();
}
return INSTANCE;
}
return INSTANCE;
}
/**实例4,存在问题:会出现INSTANCE半初始化的问题,
*INSTANCE = new DclLockTest();这行代码,编译成class文件,
* 会形成三条jvm指令,1:分配内存,2:初始化,3:变量赋值,
* 若jvm将这三条指令重排序,1->3->2,另外的线程使用未初始化的变量,
* 程序执行结果可能不是预期的,发生错误
*/
public static MultiSingletonCreateTest getInstance4() {
if (INSTANCE == null) {
synchronized(MultiSingletonCreateTest.class){
if(INSTANCE == null){
INSTANCE = new MultiSingletonCreateTest();
}
}
return INSTANCE;
}
return INSTANCE;
}
单实例创建-双重检查锁
public class DclLockTest {
private static volatile DclLockTest INSTANCE;
private DclLockTest() {
}
public static void main(String[] args) {
}
/**完美,双重检查+锁+volatile变量,volatile变量,
* 禁止jvm重排序
*
*/
public static DclLockTest getInstance5() {
if (INSTANCE == null) {
synchronized(DclLockTest.class){
if(INSTANCE == null){
INSTANCE = new DclLockTest();
}
}
return INSTANCE;
}
return INSTANCE;
}
}