Java实现单例模式

那什么是单例模式:确保一个类只有一个实例,并提供一个全局访问点。

是不是看起来很正式,哈哈哈~

也就是说让一个类运行时只产生一个对象。

单例模式可以说是众多设计模式中实现较为简单的一种设计模式。

既然比较简单,就话不多说,贴代码上来就一目了然了~

下面说这几种单例模式的实现:

  1. 懒汉式
  2. 饿汉式
  3. 双重检查式
  4. 内部类式
  5. 枚举方式

1、饿汉式
注意事项:
1)一个私有的构造器、获取类实例的静态方法
2)对象用private、static、final关键字修饰
3)浪费内存
4)线程安全

class Singleton {
    //私有构造器,确报外面不能 new 对象
    private Singleton() {}
    //造成内存浪费,每次进来先加载,再使用
    private static final Singleton instance = new Singleton();
    public static Singleton getInstance() {
        return instance;
    }
}

线程安全这里说一嘴:一般在Java 里面,static修饰的东西最先加载、只被加载一次。进来这个类,不管是线程1、线程2、线程3等等等等,instance已被加载过,就只会返回同一个类的实例。

浪费内存也是在这里:如果这个单例模式的类中还有其它代码,此时我并不想调用这个实例,但它却被加载了。

2、懒汉式
注意事项:
1)构造器私有、静态方法获取类的实例
2)static修饰的对象

线程不安全
单线程下不影响

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

1处判断之后,某个线程因为某种情况搁置了;再来另一个线程判断instance == null;这两个线程会得到不一样的对象。

线程安全

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

3、双重检查式、DCL
注意事项:
1)私有构造器
2)实例用volatile、static关键字修饰
3)线程安全

class Singleton {
    private Singleton() {}
    private static volatile Singleton instance;
    public static Singleton getInstance() {
        if (instance == null) {//1
            synchronized (Singleton.class) {
                if (instance == null) {//2
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

双重检查好处是什么呢?
没有1的判空条件,势必每个线程都要获取锁,紧接着再去执行其他操作。进行判断以后,后来来的线程就判断一次然后走开,不用加锁、释放锁;

1处操作的不足时,有可能在某个时刻有两个线程不分先后判空 instance == null

然后线程1获取锁创建一个对象、线程2获取锁会创建一个新的对象,这两个对象肯定不一样;

再在2处判断一次,保证了线程安全,提高了程序性能。由于instancevolatile关键字修饰,一经更改,背的线程就都能注意到。

4、静态内部类式
注意事项:
1)私有构造器
2)私有的静态内部类
3)线程安全

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

为什么是线程安全的呢?第一、类加载的时候是线程安全的;第二:加载一个类时,如果没有使用其内部类,该内部类是不会被加载的。内部类被加载的时候参考第一条。

5、枚举方式
注意事项:
1)无
2)推荐使用

enum Singleton {
    INSTANCE;
    //下面可以有其它方法、常量等
}

//使用
Singleton singleton = Singleton.INSTANCE;
singleton.xxx;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值