Skip to content

Latest commit

 

History

History
128 lines (72 loc) · 3.03 KB

File metadata and controls

128 lines (72 loc) · 3.03 KB

06.单例模式

单例模式应该算是设计模式里相对简单的一个。

在我们需要在系统中只能拥有一个实例时,这时候我们就需要单例模式,例如:数据库连接池、缓存池等。

##6.1 最简单的单例模式

在读书的时候,或许我们都写过这么一个单例的实现:

public class DataSource {
    private static DataSource dataSource = new DataSource();

    private DataSource() {}

    public static DataSource getInstance() {
        return dataSource;
    }
}

我们在这里将构造方法私有化,外部无法调用构造方式进行实例化。

类提供了一个getInstance方法,该方法返回一个在类加载期就初始化的DataSource实例化对象,从而保证了DataSource实例的唯一性。

##6.2 延迟创建

我们知道static标识的属性会在类初始时就进行初始化。处于性能的考虑,我们可能会希望该单例的实例化对象,在第一次使用的时候再进行初始化:

于是,有了下面的代码:

public class DataSource {
    private static DataSource dataSource = null;
    
    private DataSource(){}

    public static DataSource getInstance() {
        if (dataSource == null) {
            dataSource = new DataSource();
        }

        return dataSource;
    }
}

我们将DataSource的初始化迁移到getInstance方法里,系统会第一次调用getInstance方法的时候初始化DataSource对象。

##6.3 线程安全

上面的例子中,细心的人或许会发现:在多线程的情况下,如果第一次有N个线程同时进入getInstance方法,则会产生线程安全问题, 会多次创建DataSource对象,甚至其他问题。

为了解决线程安全问题,我们可以使用 synchronized 关键字对getInstance方法进行同步。

public class DataSource {
    private static DataSource dataSource = null;
  
    private DataSource(){}

    public synchronized static DataSource getInstance() {
        if (dataSource == null) {
            dataSource = new DataSource();
        }

        return dataSource;
    }
}

##6.3 线程安全优化

也许有人有提出问题了,在高并发的情况下,使用synchronized对整个方法进行同步会影响性能(大多数情况下没必要计较)。

解决的方法就是使用类锁代替方法锁:

public class DataSource {
    private static DataSource dataSource = null;

    private DataSource() {}

    public static DataSource getInstance() {
        if (dataSource == null) {
            synchronized (DataSource.class) {
                if (dataSource != null) {
                    dataSource = new DataSource();
                }
            }
        }

        return dataSource;
    }
}

在这个实现里使用了 double check (两次判断dataSource == null)。当多个线程同时进入第一个if判断时,double check是很有必要滴!

##6.4 静态内部类

##6.5 序列化

参考资料

  • 《Java漫谈设计模式》