嗯,一道面试题。
单例模式:某个类只能生成一个实例,且这个类能够且必须自行创建实例,该类提供了一个全局访问点供外部获取该实例。
实现的大概思路:通常普通类的构造函数是公有的,外部类可以通过"new构造函数()"来生成多个实例;将类的构造函数设为私有的,外部类就无法调用该构造函数,此时类的自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。
模式的实现:
(1)懒汉式单例:
public class LazySingleton {
private static volatile LazySingleton instance=null;//保证instance在所有线程中同步
private LazySingleton(){} //private避免类在外部被实例化
public static synchronized LazySingleton getInstance(){//实例化前加同步保证线程安全
if(instance==null){
instance=new LazySingleton();
}
return instance;
}
}
上面的懒汉式单例中有关键字volatile和synchronized能够保证在多线程模式下保证安全,但每次访问时都需要同步,会影响到性能,更高的性能还得看饿汉,但已经满足题目要求了。
(2)饿汉式单例:
public class HungrySingleton {
private static final HungrySingleton instance=new HungrySingleton();//类一旦加载就会创建,保证在调用getInstance()方法前单例就已经存在
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return instance;
}
}
饿汉式同样是线程安全的,能够直接用于多线程场景。
附录补充:
volatile关键字,不起眼,隐晦,且容易被误解,所以需要格外关注一下。
volatile作用一:64位写入的原子性,由于JVM规范没有要求64位的long或double的写入是原子的,在32位的机器上,一个64位的变量的写入可能会被拆分成两个32位的写操作来执行,这样一来在多线程环境下,读取的线程可能只读到一半的值。