单例模式
定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供。设计模式中最简单也是最理解的模式,实用性很大,通常用于访问数据库、弹出对话框、网络请求等情况。
写法
单例是自行实例化,首先把默认构造方法设置为私有,不允许外部实例化。然后内部自行实例化,最后提供一个静态方法返回这实例。
public class Singleton {
private static Singleton singleton = new Singleton();//自行实例化
private Singleton() {//私有默认构造方法
}
public static Singleton getInstance() {//对外提供实例的静态方法
return singleton;
}
}
饿汉式
上面的方式是饿汉式的写法,饿了先吃,第一次调用会快很多。但是先自行实例化,预先加载,不调用会比较浪费。所以有下面的懒汉式。
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {//调用方法时再创建
singleton = new Singleton();
}
return singleton;
}
}
懒汉式
懒汉式是比较懒,用到再创建。延迟加载也叫懒加载,好处是减少资源浪费。但是懒汉式遇到多线程它就不安全了。所以要加上同步。
……
public synchronized static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
双重检查锁
但是每次调用getInstance方法都要用到同步方法,性能一定不好。所以有了双重检查锁。第一次获取到实例,下一次第一个if语句就不再执行。意味同步方法块也是验证了那么几次,因为多线程并发有的线程已过了第一个if语句,所以里面再要判断多一次是否为null。
……
//双重检查锁
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
静态内部类
还有一种方式,静态内部类。利用ClassLoader机制,初始化只有一条线程,所以线程是安全的。而且也带懒加载。
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
}
总述
单例模式还有一种枚举实现方式,因为枚举就是天然的单例,但很少见,这里就不多讲。上面三种方式的选择取决于需求,不在意预先加载可以使用第一种,第二种和第三种几乎是一样。单例模式的运用很广泛也很容易掌握。不足之处望指教。