应用最广的模式,单列模式
单列模式是用用最广的模式之一。 在应用这个模式的时候,单例对象的类必须在整个应用中只有一个实例存在。
单例模式一般有以下几个特点:
- 构造函数不对外开放,一般都是private。
- 通过一个静态的方法或者枚举返回对象。
- 确保多线程情况下只有一个实例对象。
单例模式通常有如下几种实现情况
-
饿汉模式
`public class Config {private static Config CONIG = new Config();
private Config(){}
public static Config getInstance(){
return CONIG;
} }`
代码中Config不能通过new的方式来获得,只能通过getInstance的方式来获取。 而这个CONIG对象是静态的对象,并且在声明的时候已经初始化了,这就保证了对象的唯一性。 -
懒汉模式
懒汉模式是声明一个对象,并且在第一次调用getInstance的时候初始化。
public class Config {
private static Config CONFIG = null;
private Config(){}
public static synchronized Config getInstance(){
if(CONFIG == null){
CONFIG = new Config();
}
return CONFIG;
}
}
这种模式在getInstance方法前添加了synchronized关键字,保证他是一个同步方法,这就保证了在多线程中这个类的实例的唯一性。 但是你想下,即使Config已经被初始化了,每次调用getInstance都会进行方法同步,这就会消耗不必要的资源,这也是懒汉模式的一大缺点。 总结下,懒汉模式在第一次使用的时候才会实例化资源,最大的缺点是每次调用都需要不必要的同步,也浪费了很多资源。
- 懒汉模式的改进
public class Config {
private static Config CONFIG = null;
private Config(){}
public static Config getInstance(){
if(CONFIG == null){
synchronized (Config.class) {
if(CONFIG == null){
CONFIG = new Config();
}
}
}
return CONFIG;
}
}
这个改进都在getInstance上,进行了两次判空,一次同步。 第一个判断空是为了不必要的同步,第二次判断空是为了避免在多线程情况下多次创建实例。 因为假如有两个线程同时进入了第此判空,其中一个阻塞到synchronized之外,如果不判断空,第二个线程在执行的时候也会创建一个实例。
- 静态内部类实现单例模式
public class Config {
private Config(){}
public static Config getInstance(){
return Holder.CONFIG;
}
private static class Holder{
private static Config CONFIG = new Config();
}
}
这种模式只有当第一次调用getInstance的时候初始化,并且有JVM来保证线程安全与唯一性。 这种方法是推荐使用的单例模式。
- 枚举单例
这种模式还在研究之中,暂不做解释
网友评论