设计模式-单例模式

单例模式算是设计模式中最简单的模式,在我们的项目中经常会用到,网上资料也很多,我这主要讲单例模式的使用场景及单例模式的特性。

先看个简单单例模式例子:

public class Singleton {
    private static Singleton singleton;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }

        return singleton;
    }
}

下来进行测试:

public class TestSingleton {
    @Test
    public void test() {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        
        System.out.println(singleton1);
        System.out.println(singleton2);
    }
}


输出结果:

com.design.pattern.Singleton@30946e09
com.design.pattern.Singleton@30946e09

可见对象的结果一样,说明无论你调用多少次,Singleton类只会生成一个对象,这就是单例模式。

下来看下满足单例模式的条件:

1.私有构造方法,禁止通过new创建对象。否则单例模式就是去意义了。

2.自己的静态实例,指向自己的static变量。

3.返回自己静态实例的静态公有方法

4.判断自己的静态变量是否为null,为null创建个对象否则直接返回。


单例模式优点:

无论怎么调用都只有一个对象,节省内存空间,

避免频繁创建销毁对象,提高性能

避免对共享资源的多重占用

可以全局使用


下来我讲单例模式在多线程下的

@Test
    public void test_multhread() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 100; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    Singleton singleton = Singleton.getInstance();
                    System.out.println(singleton);
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
        }
    }


输出结果:

com.design.pattern.Singleton@5196823d
com.design.pattern.Singleton@70a924d6
com.design.pattern.Singleton@5196823d
com.design.pattern.Singleton@5196823d 

......

看到没,出现了多个实例,

所以在并发情况下,这种单例模式是不稳定的。

那我们如何保证并发情况下也只有这一个实例呢,那就是加锁。

public synchronized static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }

在这里我们把整个方法同步,一次只能一个对象调用,避免多个对象调用;但是这会造成后面的对象挂起,必须等前面的处理完才能进行,效率非常低。如果对象已经有实例,就不需要进到if判断,但是还是得等待,这势必浪费资源。

我们再次优化,缩小同步的范围:

public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }
这样就过滤掉已经有实例情况下,不需要再等待,效率提升。但是这块有个潜在的问题,如果A和B同时进到if判断里面,A先操作,new一个实例,B进来的时候还是会再new一个实例,这就违背单例模式的初衷,那在B进入的时候判断下是否A已经实例化过了,如果实例化了就直接返回实例。

再次优化如下:

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










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值