今天面试的时候面试官让我写一个单例模式,然后我就写了一个双重检验锁的单例模式,但是在问如果去掉一个验证后为什么不行的时候,我当时说的有点乱七八糟的,很是不好,重新整理之后,我发现我竟然写错了好几个地方的代码。所以我就想记录一下这个问题,实现单例模式的几种方法。
饿汉式创建单例模式,就是在类初始化的时候就已经建立好了单例。使用final修饰符进行修饰,表示这是一个静态的变量,初始化赋值之后就不能再次赋值了。
public class Singleton{
public final static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
也就是懒加载模式,只有在使用的时候才会进行加载。必须保持线程的初始化。
该方法中使用的volatile修饰instance,当instance被修改后,其他的线程也可以立马获取变量。使用synchronized锁来锁定该字段,并且锁定代码块,确定只有一个线程能够进入该代码块。第2重验证防止其他线程提前进入了synchronized同步块后已经实例了该对象,而本线程又重复进入了该同步代码块,所以需要再次进行验证。
volatile: 一定要记得把java的关键字全部要写一下,千万不要写错了,我在面试的时候就把这个单词写错了。。。。。
如果没有第二重验证会怎么样?
答案是:如果有两个线程同时竞争synchronized修饰的代码块的时候,就会有instance被实例化了两次,这个时候就会有instance指向了两个不同的对象。这就违背了单例模式的本意,所以需要进行两次验证。
注意:在静态方法中,synchronized方法不能使用
synchronized(this)
,只能使用synchronized(Singleton.Class)
方法,只能锁定整个方法区域。
public class Singleton{
public static volatile Singleton instance = null;
public static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
使用同步方法直接加在了方法上,这种方法保证了线程的安全性。但是这种方法的性能要比双重验证的方法性能要低,是因为双重验证方法中,只有第一次判断instance为null的时候才会进入同步方法块,其他的线程才会被阻塞。但是使用同步静态代码块中每一次获取实例,都会进入同步代码块,如果有多个线程同时获取,那么只有一个线程能够获取,其他的线程都会被堵塞,这样就会降低程序的性能。
public class Singleton{
public static Singleton instance = null;
public synchronized static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
这种方法通过java的定义实现了同步,并且
public class Singleton{
private static class SingleHolder{
public static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingleHolder.INSTANCE;
}
}
EasySingleton.INSTANCE
public enum EasySingleton{
INSTANCE;
}
完整的代码为:
public class Singleton{
// 使用枚举的方法创建单例模式
public enum EasySingleton{
INSTANCE;
private final Singleton instance;
EasySingleton() {
instance = new Singleton();
}
public Singleton getInstance(){
return instance;
}
}
// 获取静态实例的方法
public static Singleton getInstance(){
return EasySingleton.INSTANCE.getInstance();
}
}
原文:https://www.cnblogs.com/liulongtao/p/14651178.html