1、饿汉式
饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要判断了,节省了运行时间。
如果一个类中的成员属性比较少,占用的资源不多时,可以考虑。相反,如果类中成员都是比较重的资源,这种方法有所不妥。
public class Singleton {
/*
* 饿汉式
*/
private static Singleton singleton = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
2、懒汉式
单例模式的懒汉式体现了缓存的思想,延时加载就是一开始不要加载资源或者数据,一直等,等到马上就要使用这个资源的或者数据了,躲不过去了才去加载。懒汉式是定性的时间换空间,不加同步的懒汉式是线程不安全的
public class Singleton {
/*
* 懒汉式
*/
private static Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if(singleton==null) {
singleton = new Singleton();
}
return singleton;
}
}
3、懒汉式+同步
synchronized关键字天生的排他性导致了getInstance方法只能在同一时刻被一个线程所访问,性能低下。
public class Singleton {
/*
* 懒汉式
*/
private static Singleton singleton = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(singleton==null) {
singleton = new Singleton();
}
return singleton;
}
}
4、双重检查加锁(Double-Cheak)
首次初始化时加锁,之后则允许多个线程同时对getInstance进行访问。
public class Singleton {
/*
* 懒汉式
*/
private volatile static Singleton singleton = null; // volatile保证了可见性
private Singleton() {}
public static Singleton getInstance() {
if(singleton==null) {
synchronized (Singleton.class) {
if(singleton==null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
5、静态内部类
当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致SingletonHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。
public class Singleton {
private static class SingletonHoler {
/**
* 静态初始化器,由JVM来保证线程安全,静态内部类只能加载一次
*/
private static Singleton instance = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHoler.instance;
}
}
6、使用枚举
public enum DataSourceEnum {
DATASOURCE;
private DBConnection connection = null;
private DataSourceEnum() {
connection = new DBConnection();
}
public DBConnection getConnection() {
return connection;
}
}