单例模式几种写法,安全 不安全 懒汉 饿汉
单例模式几种写法,安全 不安全 懒汉 饿汉
单例模式在平常中运用较多,而且在面试中更是被经常提及
单例模式有几个重点是懒汉模式,饿汉模式,线程安全,线程不安全
这个是最普通的单例模式,这个是懒汉式,线程不安全
//这个是普通的单例模式
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if (instance === null) {
instance = new Singleton();
}
return instance;
}
}
**懒汉式,线程安全类型**
//这个是线程安全的单例模式
//这个在调用的时候回锁住整个方法,效率不是很好
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static synchronized getInstance(){
if (instance === null) {
instance = new Singleton();
}
return instance;
}
}
虽然这个是线程安全,但是效率不是很好,因为在任何时候只有一个线程能调用getInstance()方法。
下面我们就使用双重检验锁来解决这个问题。
双重检验锁是对同步块加锁的方法。为什么会称为双重检验,因为有两次对 instance == null的检查,一次中同步块中一次中同步块外部。
为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话就会生成多个实例了。
//这个是线程安全的是效率比较好的
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if (instance == null) {
synchronized(Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
上面的不是都是懒汉模式的,下面我们来介绍一下关于饿汉模式的
饿汉模式 static final field 这种方法也是很简单,只需要将单例的实例声明为static何final变量。这是因为在第一次加载到内存中的就会被初始化,所以创建实例本身是线程安全的。
public class Singleton{
//类加载时就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
**静态内部类 stat nested class**
//懒汉式的静态内部类
public class Singleton{
private static class SingletonInner{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton{
}
private static final Singleton getInstance(){
return SingletonInner.INSTANCE**strong text**;
}
}
这是目前最好的解法,既是线程安全又无其他的问题。