Java设计模式之单例模式

单例模式(Singleton Pattern)是一种简单的对象创建型模式。该模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。

所以要实现单例模式,要做到以下几点:

  • 将构造方法私有化,杜绝使用构造器创建实例。
  • 需要自身创建唯一的一个实例,并提供一个全局访问入口
饿汉式

所谓饿汉式,就是直接创建出类的实例化,然后用private私有化,对外只用静态方法暴露。

public class Singleton {
    // 1、构造私有 判断INSTANCE是否为null,防止通过反射创建新对象
    private Singlgton() {
        if(INSTANCE != null) {
            throw new RunTimeException("单例对象不能重复创建!");
        }
    }

    // 2、私有静态成员变量
    private static Singleton INSTANCE = new Singleton();
    
    // 3、公共方法获取实例
    public static Singleton getIntance() {
        return INSTANCE;
    }

    // 4、解决反序列化创建实例
    public Object readResolve() {
        return INSTANCE;
    }
}
枚举式

其实,使用枚举也能实现单例模式,不仅能避免多线程同步问题,也能防止反序列化重新创建新的对象。

public enum Singleton {
    INSTANCE;
}

//测试
public static void main(String[] args) {
	Singleton instance1 = Singleton.INSTANCE;
	Singleton instance2 = Singleton.INSTANCE;
	System.out.println(instance1 == instance2);
	
	System.out.println(instance1.hashCode());
	System.out.println(instance2.hashCode());
}

运行结果

在这里插入图片描述

懒汉式

所谓懒汉式,就是在需要调用的时候再创建类的实例化。

  • 线程不安全

    起到了懒加载效果,但是只能在单线程使用,多线程会不安全,因为当多个线程并发同时判断instance为空时,就会相应的实例化多个对象。

    public class Singleton() {
        private Singleton(){}
    
        private static Singleton INSTANCE;
    
        public static Singleton getIntance() {
            if(INSTANCE == null) {
                INSTANCE = new Singleton();
            }
            return INSTANCE;
        }
    }
    
  • 线程安全

    上面线程不安全,那上锁不就好了,使用synchronized关键字。这样虽然解决了线程安全,但其实实例化操作只做一次,而获取实例(即getInstance)的操作是很多次的,把调用的方法加上同步,会大大降低效率。

    public class Singleton {
        private Singleton(){}
    
        private static Singleton INSTANCE;
    
        public static synchronized Singleton getInstance() {
            if(INSTANCE == null){
                INSTANCE= new Singleton();
            }
            return INSTANCE;
        }
    }
    
  • 双重检查

    上面代码效率低,那在同步前判断一下有没有实例化不就好了,若没有实例化则用同步方法new一个,否则直接return即可。即所谓的双重检查。
    需要用到关键字volatile,防止指令重排。如果不用volatile关键字,就会和线程不安全情形一样,在if判断那会有并发。

    public class Singleton {
        private Singleton() {}
        
        private static volatile Singleton INSTANCE;
    
        public static Singleton getInstance() {
            if(INSTANCE == null) {
               synchronized (Singleton.class) {
                   if(INSTANCE == null) {
                       INSTANCE = new Singleton();    
                   }
               } 
            }
            return INSTANCE;
        }
    }
    
  • 静态内部类

    静态内部类在外部类装载时不会实例化,当调用的时候才会装载并实例化,且JVM保证了其装载时的线程安全性。也能保证懒加载和线程安全,有点像自带版的双重检查。

    public class Singleton {
        private Singleton() {}
        
        public static synchronized Singleton getInstance() {
            return SingletonInstance .INSTANCE;
        }
        
        private class SingletonInstance {
            static Singleton INSTANCE = new Singleton();
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lucky赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值