单例模式
项目启动时,会有多个线程来访问。如果一个类是不能被改变的,如果不适用单例模式,每一个先知执行时创建一个对象。对象创建的多了,必然会引起内存泄漏。想想淘宝网站,双十一零点,几百万人访问淘宝,单个类,被创建了几百万次,即使内存不泄露,访问也会比较缓慢。
所以,应该尽可能把一些不能被改变的类,设计成单利模式。
单例模式和上面的工厂模式一样,如果引入了spring,基本已经被spring代替了。spring的注解@component如果不设置scope,即默认为单利的。
一、简单实现
最简单的单例模式实现方式,一共两步:
* 私有构造器
* 提供静态变量
public class Single{
private Single(){};
public static Single SINGLE = new Single();
//...其他方法
}
这是最简单的一个单利模式的实现。也被称为饿汉式。即类被初始化的时候就把对象创建出来了。
它的优缺点:
- 优点
简单,不会存在多线程环境下,被创建多个对象的情况。
- 缺点
如果某个类很少被适用到,项目启动时就被创建了出来,这样会比较浪费内存。内存中白白存放一个不用的对象。
二、需要时创建
简单方式有了缺点,就有新的改进办法。即可以在它第一次被适用的时候来创建。
public class Single{
private Single single;
private Single(){};
public Single getInstance(){
if (single == null) {
single = new Single();
}
return single;
}
//...其他方法
}
这样的话,即能在被第一次使用的时候被创建。但是这样同样具有一个问题,多线程环境下面,如果存在并发情况,将会创建多个对象。
A线程进来,调用getInstance()方法,发现single为null,正要准备创建对象。
B线程进入,发现single也为null。也要创建对象。
这样的话,即创建了两个对象。解决方法是在这儿创建时,增加同步情况。
public class Single{
private Single single;
private Single(){};
public Single getInstance(){
if (single == null) {
synchronized (Single.class) {
single = new Single();
}
}
return single;
}
//...其他方法
}
同步方法将会比较慢,虽然说只是在第一次使用的时候才会出现。不过还有一种写法是,提供静态内部类。内部类创建是同步的。
public class Single{
private Single(){};
private static class SingleHolder {
private static Single single = new Single();
}
public Single getInstance(){
return SingleHolder.single;
}
//...其他方法
}
上面是单例模式的几种实现方法。