java static 对象加锁_Java学习——单例模式

本文详细介绍了单例模式的概念及其在软件开发中的应用。探讨了单例模式的多种实现方式,包括懒汉式、饿汉式、双重校验锁、静态内部类及枚举方式,并分析了各自的优缺点。

f1ab2c397768ad4fbfd5d98451d20f82.png

GOF四人合著出版了一本名为Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素)的书,共有23种设计模式,而这些设计模式又分为3大类:

1、创建型模式

2、结构型模式

3、行为型模式


单例模式属于第一种,是创建型模式

什么是单例模式呢?what?

答:顾名思义,就是单一的一个实例(只有一个对象)的模式

为什么只需要一个实例,有个鸟用?

答:一个全局使用的类频繁的创建与销毁,浪费时间,消耗资源。

有鸟用啊,当我们想控制一个类的实例数目,节省系统资源的时候。

那它是怎么做到只有一个实例的呢?

我们知道,构造器是用来创建对象的(实例化),我们只需要让该类的构造器私有

551d31debb938866ec5af504bf02fe75.png

应用的实例:

一个班级只有一个班主任,一个帝国只有一个国王。

Windows系统是多进程多线程的,在操作一个文件的时候,就不可避免多个进程或者多个进程同时操作这一个文件对象,所以所有文件的处理必须通过唯一的实例来进行。

优点:只有一个实例,减少内存的开销,频繁的创建和销毁实例。

缺点:没有接口,不能继承。

使用场景:

Java中的IO与数据流的连接等。

几种实现方式:

1、懒汉式(lazy loading),线程不安全(没有用synchronized修饰那个得到的方法)

很懒,很懒,很懒,这种实现的方式就是不支持多线程。严格意义他不是单例模式

第一次调用getInstance()的时候才去创建那个单例对象

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

我们来看加锁的,加了synchronized

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

虽然支持了多线程,但是加锁会影响效率,

2、饿汉式

很饥渴、很饥渴、很饥渴

比较常用的方式,不调用getInstance()方法就已经有对象,所以容易产生垃圾对象。

缺点:类加载的时候就初始化,浪费内存。

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}

3、双重校验锁(双重保险)

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

使用synchronized锁住了代码块,如果为空则判断是否有线程持有该锁,则等待,不为空则直接返回这个单例对象。

4、使用静态内部类来实现

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

Java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。

被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类

需要注意的是当一个内部类没有使用static修饰的时候,是不能直接使用内部类创建对象,须要先使用外部类对象点new内部类对象及(外部类对象.new 内部类())

5、枚举

这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  

 

用这种方式写不免让人感觉生疏,在实际工作中,也很少用。

经验之谈:

不建议使用懒汉式,建议使用饿汉式,很饥渴,很饥渴,很饥渴的那种,

只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。

以上学习来自菜鸟教程。

单例模式 | 菜鸟教程​www.runoob.com
68fb30b1b84dee87b663a54e2725cb21.png
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值