目录
单例模式使用场景->
[三种情况都经过代码测试]
第一种: 饿汉式(内存占用问题)
实现简单
服务开启的时候创建(一般小对象,频繁用) 缺点: 消耗资源非常大
->上代码:
class Singleton {
/**
* 饿汉式
*/
private Singleton() {
} //这样其他不能new了
private static final Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
第二种: 懒汉式(线程安全问题)
一般会出现多线程并发安全问题 只能加锁 如果直接加锁 性能非常差, 只能有条件的锁 没创建锁一次即可
采用双重验证
->上代码
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) { //这步等效于在方法上添加synchronized
if (instance == null) {
System.out.println("====> 只能执行第一次!!! <===");
instance = new Singleton();
}
}
}
return instance;
}
第三种: 登记式(特殊)
具体情况介绍:
创建一个实例 有的时候,我们不希望在一开始的时候就把一个类写成单例模式,但是在运用的时候,我们却可以像单例一样使用他 最典型的例子就是spring,他的默认类型就是单例,spring是如何做到把不是单例的类变成单例呢? 这就用到了登记式单例 其实登记式单例并没有去改变类,他所做的就是起到一个登记的作用,如果没有登记,他就给你登记,并把生成的实例保存起来,下次你要用的时候直接给你。 IOC容器就是做的这个事,你需要就找他去拿,他就可以很方便的实现Bean的管理
->上代码:
private Singleton() {}
public static Singleton getInstance() {
return SingleNew.NEW_SINGLE;
}
private static class SingleNew {
private static final Singleton NEW_SINGLE = new Singleton();
}
测试代码:
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
};
Thread thread1 = new Thread() {
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
};
thread.start();
thread1.start();
thread2.start();
}
测试结果:
====> 只能new执行第一次!!! <====
com.jt.common.mode.Singleton@5d7aa6cf
com.jt.common.mode.Singleton@5d7aa6cf
com.jt.common.mode.Singleton@5d7aa6cf
单例模式使用场景->
看到一篇文章, 感觉不错