java设计模式-单例模式

对一些重要资源的访问, 有时需要实例创建只有一份, 那么实例创建就需要用到单例模式 .


恶汉式:

在类初始化时候就加载了对象, 可以不用考虑多线程问题 .
缺点 : 如果对象创建比较耗资源, 提前加载会耗费性能 .

/**
 * 恶汉式
 * @author 张延
 *  */
public class SingleInstance {
    // 类初始化就加载这个对象, JVM初始化是线程安全的
    private static SingleInstance singleInstance = new SingleInstance();
    // 私有化构造器
    private SingleInstance(){};
    // 提供一个公共的获取对象方法
    public static SingleInstance getInstance() {
        return singleInstance;
    }
}

懒汉式:

  • 不加锁
    多线程情况会出现问题, 可能会导致两份实例创建
/**
 * 懒汉式
 * @author 张延
 *  */
public class SingleInstance {

    private static SingleInstance singleInstance = null;
    private SingleInstance(){};
    public static SingleInstance getInstance() {
        if(singleInstance == null) {
            singleInstance = new SingleInstance();
        }
        return singleInstance;
    }
}
  • 加锁方式
    针对上面不安全方式改进, 但是这种synchronized修饰方法会导致性能降低, 因为getInstance是一个频繁被使用方法,
/**
 * 加锁的懒汉式
 * @author 张延
 *  */
public class SingleInstance1 {

    private static SingleInstance1 singleInstance = null;
    private SingleInstance1() {};
    // 在方法上加锁,限制多个线程同时进入,导致实例化不是一份
    public synchronized static SingleInstance1 getInstance() {
         if(singleInstance == null) {
             singleInstance = new SingleInstance1();
         }
         return singleInstance;
    }

}
  • 双重锁检查
    将锁的粒度降低, 多线程都可以进去判断”null == singleInstance” , 只有当没有实例创建才会进入同步快, 再次检查是否创建, 如果没有创建,才会创建这个实例 .
/**
 * 双重锁检查的懒汉式
 * @author 张延
 *
 */
public class SingleInstance2 {

    private volatile static SingleInstance2 singleInstance = null;
    private SingleInstance2() {};
    public static SingleInstance2 getInstance() {
        // 多线程可以进来判断是否为null,只有当没有创建实例,才会进入同步代码快
        if(singleInstance == null) {
            // 将锁的粒度降低,
            synchronized (SingleInstance2.class) {
                if(singleInstance == null) {
                    singleInstance = new SingleInstance2();
                }
            }
        }
        return singleInstance;
    }
}

静态内部类方式:

基本具备很多优点 , 高校调用 , 延时加载 , 线程安全
SingleInstance类被加载, 但是instance不会被初始化, 可以做到延时加载, 只有当主动获取实例变量, 才会显示加载类, 因为JVM是天然线程安全的, 不会加载两份, 所以实例化instance很耗资源, 应该让他延时加载 .

public class SingleInstance {

    // 初始化SingleInstance的时候,内部类InnerClass不会被加载,只有在被主动使用才会加载
    private static class InnerClass {
        private static SingleInstance singleInstance = new SingleInstance();
    }
    private SingleInstance() {};

    public static SingleInstance getInstance() {
        // 当这里主动使用, 才会加载InnerClass,才会创建SingleInstance实例
        return InnerClass.singleInstance;
    }
}

总结:

饿汉式 : 线程安全 , 调用效率高 , 但是不能延时加载
懒汉式(加锁) : 线程安全 , 调用效率不高 , 但是可以延时加载
静态内部类 : 线程安全 , 调用效率高 , 并且还可以延时加载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值