Java设计模式之单例模式

本文介绍了单例模式,其确保某个类只有一个实例并向系统提供。单例类有只能有一个实例、自行创建唯一实例、向其他对象提供实例等特点。还阐述了几种实现方式,包括饿汉式、懒汉式,以及懒汉式的线程安全和高效线程安全版本,并分析了各方式的优缺点。
定义

单例模式(Singleton Pattern):确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

特点

1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

几种实现方式
饿汉式
public class SingletonHungry {
    private static SingletonHungry singletonHungry = new SingletonHungry();
    private SingletonHungry() {
		System.out.println("SingletonHungry is create");
    }
    public static SingletonHungry getInstance() {
        return singletonHungry;
    }
}

缺点:Singleton实例在什么时候被创建是不受控制的,对于静态成员singletonHungry,它会在类第一次初始化的时候被创建,如果该函数里面有一个静态成员变量,外部有方法引用了这个静态成员变量,该类就会被初始化,那么singletonHungry也会被创建。
解决办法如下:
只有在getInstance()方法被第一次调用的时候,SingletonHungry的实例才会被创建,这个方法巧妙地使用了内部类和类的初始化方法,内部类SingletonHolder被申明为private,使得我们不可能在外部访问并初始化他,只可能在getInstance()内部对SingletonHolder类进行初始化,利用虚拟机的类初始化机制创建单例。

public class SingletonHungry {
    private SingletonHungry() {
        System.out.println("SingletonHungry is create");
    }
    private static class SingletonHolder {
        private static SingletonHungry instance = new SingletonHungry();
    }
    public static SingletonHungry getInstance() {
        return SingletonHolder.instance;
    }
}
懒汉式

线程不安全,也就是说第一个线程刚好执行到判断为null的时候,第二个线程也进来了,这样就造成了生成两个实例。

public class SingletonDemo {

    private static SingletonDemo singletonDemo = null;

    /**
     * 这里首先要私有构造函数,不允许new实例,只提供一个公共的创建实例方法
     */
    private SingletonDemo() {

    }

    /**
     * 这里用到static是因为这个类构造函数私有化了,不能new实例出来,只有用类直接调用静态方法
     * @return
     * @throws SingletonException
     */
    public static SingletonDemo getSingleton(){
        if (singletonDemo == null) {
            singletonDemo = new SingletonDemo();
        }
        return singletonDemo;
    }

    public void showSingleton() {
        System.out.println("我是单例模式哦!");
    }
}
懒汉式线程安全

直接在创建实例的方法上加synchronized ,这样虽然避免了线程不安全的问题,但是执行效率会很低。

public static synchronized SingletonDemo getSingleton(){
        if (singletonDemo == null) {
            singletonDemo = new SingletonDemo();
        }
        return singletonDemo;
    }
懒汉式高效线程安全

当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

public class SingletonDemo {

    private volatile static SingletonDemo singletonDemo = null;

    private SingletonDemo() {

    }

    public static SingletonDemo getSingleton(){
        if (singletonDemo == null) {
            synchronized (SingletonDemo.class) {
                if (singletonDemo == null) {
                    singletonDemo = new SingletonDemo();
                }
            }
        }
        return singletonDemo;
    }

    public void showSingleton() {
        System.out.println("我是单例模式哦!");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值