单列模式的要点:
1.单列模式确保程序中一个类最多有一个实例。
2.单例模式提供全局访问该单列的点(类的静态方法)。
3.java 中实现单列模式需要一个私有构造器,一个static方法返回实例,一个static变量。
4.注意:如果有多个类加载器可能导致单例模式失效产生多个实例。
许久不写单列,突然要去写个单例,我会写出这种不安全的:
public class SingleMode {
private static SingleMode uniqueSingleMode;
private SingleMode(){
}
public static SingleMode getInstance(){
if (uniqueSingleMode == null){
uniqueSingleMode = new SingleMode();
}
return uniqueSingleMode;
}
}
这样的写法不能保证在多线程的并发访问的情况下只生成一个单列。
通常单例模式分恶汉模式和懒汉模式,区分就是需不需要提前实例化。
下面是一个恶汉模式:
public class HungrySingleMode {
private static HungrySingleMode hungrySingleMode = new HungrySingleMode();
private HungrySingleMode(){
}
public static HungrySingleMode getInstance(){
return hungrySingleMode;
}
}
它是通过静态常量实例化一个对象,这样能保证多线程情况下的安全,在需要用的时候直接返回实例化好的对象。
之前工作中有通过在类中通过静态变量实例化一个线程池对象,然后在需要使用的地方直接通过类名调用,很方便。感觉和恶汉模式有点像但还是有些区别的(不建议用这种方式获取一个单列)。
下面是一个懒汉模式:
public class LazySingleMode {
//使用volatile让常量在线程之间可见
private volatile static LazySingleMode lazySingleMode;
public static LazySingleMode getInstance(){
if (lazySingleMode == null){
//获取类的锁,防止多线程并发,锁在代码块上而不是方法上,锁在方法上的性能太低
synchronized (LazySingleMode.class){
//再次判断对象是不是空,可能上一个线程刚释放锁,对象已经实例化了,lazySingleMode在线程之间可见
if (lazySingleMode == null){
lazySingleMode = new LazySingleMode();
}
}
}
return lazySingleMode;
}
}
懒汉模式在要用到对象的时候才去实例化,很多情况下单列的实现都是用的这种,单例模式的总结就到这里。