设计模式篇之单例(一)
单例模式是最简单的设计模式之一。当某个类只需要一个实例时,我们可以用这种模式,比如数据库的连接,可以提高效率,避免资源浪费。
单例设计模式可分为懒汉和饿汉两种模式。
1、饿汉:
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
之所以被称为饿汉式,是因为在类加载的时候,就初始化了所需要的唯一实例。这是一种最简单的实现方式,构造函数的private属性保证了该类不会再有第二个实例。由于类被加载的时候,就已经有了该事例,所以这种实现方式是线程安全的。
2、懒汉式
public class Singleton2 {
private Singleton2(){}
private static Singleton2 singleton2 = null;
public static Singleton2 getInstance(){
if(singleton2 == null){
singleton2 = new Singleton2();
}
return singleton2;
}
}
区别于饿汉式,懒汉式只有在被使用的时候,才会产生唯一的实例。但因此也产生了另一个问题,在修改singleton2的时候,可能会受到访问对象数量和访问速度的影响,而出现多个实例的状况,所以说是线程不安全的。
3、懒汉式2.0
public class Singleton2 {
private Singleton2(){}
private static Singleton2 singleton2 = null;
public static synchronized Singleton2 getInstance(){
if(singleton2 == null){
singleton2 = new Singleton2();
}
return singleton2;
}
}
将获取实例的方法加上同步,使之成为同步函数,对内部资源进行互斥访问,便可解决线程不安全的问题。但随之而来的新问题,也需要解决一下,那就是效率问题。
4、懒汉式3.0
public class Singleton2 {
private Singleton2(){}
private static Singleton2 singleton2 = null;
public static Singleton2 getInstance(){
if(singleton2 == null){
synchronized (Singleton2.class){
if(singleton2 == null){
singleton2 = new Singleton2();
}
}
}
return singleton2;
}
}
注意到,如果使用同步函数,那么将会对内部所有代码上锁,意味着每次调用该实例,都要判断一下,效率很低。然而真正要考虑线程安全的地方仅仅是初始化实例的时候。所以为了提高效率,在锁代码块之前,先判断一下需不需要new实例,即是不是第一次访问。这样,大部分情况下不需要进同步块,提高了效率。
如有错误,欢迎批评指正。