单利模式是一种创建模式,只提供一个实例供外部使用:
私有化构造方法(private);
在其内部产生实例化对象;
定义一个静态方法返回该类的实例。
五种单例模式:
一、只适合单线程
public class Singleton {
/** 持有私有静态实例,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/** 私有构造方法,防止被实例 */
private Singleton(){}
/** 静态工程方法,创建实例 */
public static Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
缺点:只适合单线程,如果多个线程就会出现问题
二、多线程可以使用(懒汉模式)
public class Singleton {
/** 持有私有静态实例,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/** 私有构造方法,防止被实例 */
private Singleton(){}
/** 静态工程方法,创建实例, */
public static synchronized Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
缺点:synchronized关键字锁住的是这个对象,每次访问getInstance()时都会对对象上锁,这样性能有所下降,加锁比较耗时,能避免就避免
三、加同步锁并且让两次判断
public class Singleton {
/** 持有私有静态实例,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/** 私有构造方法,防止被实例 */
private Singleton(){}
/** 静态工程方法,创建实例 */
public static Singleton getInstance(){
if(instance==null){
synchronized (instance) {
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
缺点:存在两次if判断,复杂,且容易出错,如果A、B两个线程同时进入了第一个if判断,此时instance为空,所以执行了instance = new Singleton(),当B进入时,此时instance已经不再为null,B要使用Singleton实例,却发现它没有被初始化,此时便会发生错误
四、饿汉式
public class Singleton {
/** 持有私有静态实例 */
private static Singleton instance = new Singleton();
/** 私有构造方法,防止被实例 */
private Singleton(){}
/** 静态工程方法,创建实例 */
public static Singleton getInstance(){
return instance;
}
}
缺点:没有达到延迟加载(lazy loading),加载时就被初始化,浪费内存
五、内部类来维护单例
public class Singleton {
/** 私有构造方法,防止被实例 */
private Singleton(){}
/** 使用内部类来维护单例 */
private static class SingletonFactory{
private static Singleton instance = new Singleton();
}
/** 获取实例 */
public static Singleton getInstance(){
return SingletonFactory.instance;
}
}
达到了延迟加载(lazy loading)效果。
一般情况下,不建议使用一、二两种方式,其它三种方式根据具体情况来使用。