Java设计模式(3)之单例模式

单例模式

保证在同一个JVM中,同一个对象只存在一个实例。

类型:创建型模式


单例模式分为以下两种主流的形式:

  • 懒汉模式
  • 饿汗模式

两种形式的区别:

懒汉模式,在调用实例方法的时候才会实例化对象;饿汉模式在单例类被加载时候,就实例化一个对象交给自己的引用。饿汉模式不存在线程安全问题,懒汉模式需要考虑线程安全问题。


饿汉模式示例:

/**
 * Create by zhaihongwei on 2018/3/12
 */
public class HungrySingleton {

    // 私有化构造方法,防止外部实例化
    private HungrySingleton() {
    }

    // 饿汉模式在类加载的时候,对象就已经被实例化
    private static HungrySingleton hungrySingleton = new HungrySingleton();

    // 获取实例的方法
    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
}

懒汉模式示例:

最简单的懒汉模式示例:

/**
 * Create by zhaihongwei on 2018/3/12
 */
public class LazySingleton {

    // 私有化构造方法,防止外部实例化
    private LazySingleton() {
    }

    // 懒汉模式,在类加载的时候并不实例化对象,而是在第一次调用获取实例化方法的时候实例化对象
    private static LazySingleton lazySingleton = null;

    // 获取对象实例的的方法
    public static LazySingleton getInstance() {

        // 判断实例是否为空,为空则创建实例
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton();
        }

        // 不为空,说明不是第一次调用获取实例的方法,直接返回实例。
        return lazySingleton;
    }
 }

这种懒汉模式并不能解决高并发问题,是线程不安全的。以下是进行改造的:

// 获取对象实例的的方法加上synchronized 锁机制
public static synchronized LazySingleton getInstance() {

    // 判断实例是否为空,为空则创建实例
    if (lazySingleton == null) {
        lazySingleton = new LazySingleton();
    }

    // 不为空,说明不是第一次调用获取实例的方法,直接返回实例。
    return lazySingleton;
}

但是这种synchronized关键字直接加在方法上,性能会有所下降,因为每次调用getInstance(),都需要将对象加锁,但是实际上我们只需要在第一次创建实例对象的时候需要加锁,所以有了以下改进:

// 获取对象实例的的方法
public static LazySingleton getInstance() {

    // 判断实例是否为空,为空则创建实例,通过双重检查的方式,完成实例第一次创建的时候加锁。
    if (lazySingleton == null) {
        synchronized (LazySingleton.class) {
            if(lazySingleton == null) {
                lazySingleton = new LazySingleton();
            }
        }
    }

    // 不为空,说明不是第一次调用获取实例的方法,直接返回实例。
    return lazySingleton;
}

还有一种通过静态内部类的形式完成实例的创建:

/**
 * Create by zhaihongwei on 2018/3/12
 */
public class LazySingleton {

    // 私有化构造方法,防止外部实例化
    private LazySingleton() {
    }

    // 通过静态内部类的形式完成实例的创建
    private static class LazySingletonFactory {
        private static final LazySingleton lazySingleton = new LazySingleton();
    }

    // 获取实例的方法
    public static LazySingleton getInstance() {
        return LazySingletonFactory.lazySingleton;
    }
}

使用这种静态内部类的形式完成实例的创建,原理是使用JVM类加载机制,JVM类加载机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的,所以当我们第一次调用getInstance()方法的时候,JVM能够保证实例只被创建一次,并且这种方式也只会在第一次调用的时候才会使用线程互斥机制,这种形式可以很好的解决线程安全问题,并且解决性能问题。具体使用哪种形式还需要根据不同的场景进行选取。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值