在着里我们先了解什么是单例模式。
就是某个类在进程中只能有单个实例,这里的单例模式需要一定的编程技巧,做出限制,一旦程序写的有问题,创建了多个实例,编程就会报错。
如果我们学会了单例模式,这种模式会提高我们的下限。
其中单例模式包含了两种模型,一种是饿汉模型,另一种是懒汉模型,这里的懒汉模型尤为重要,面试也会考。
饿汉模型
这里的单列就是指一个对象,instance。
如代码:
class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
这里我们采用 static 来修饰 instance ,因为当初始化的时候只执行一次。
还有当我们想要获取 instance 变量的时候,直接调用getInstance方法就行了,这样我们不用重新在new了。
上述的代码,是饿汉模型。
懒汉模型
这里的懒汉模型不是在程序创建的时候new,而是第一次使用的时候才去创建,这样就可以节省当不用时,我们不用创建的开销。
如代码:
class SingletonLazy {
private static SingletonLazy instance = null;
public SingletonLazy getinstance(){
if(instance == null){
instance = new SingletonLazy();
}
return instance;
}
}
如上述代码,我们可以看到,就是调用的时候就用。
那么,如果这样是否会引起线程安全问题呢?
答案会引起线程安全问题。
在这里我们当有两个线程同时运行的时候,其线程1和线程2,同时进入if判定,都为true,此时我们就会出现两个,new了,直接就报错了。
那么这里我们加上锁之后,会不会线程安全了呢?
如代码:
class SingletonLazy {
private static SingletonLazy instance = null;
public static Object locker = new Object();
public SingletonLazy getinstance(){
if(instance == null){
synchronized (locker){
instance = new SingletonLazy();
}
}
return instance;
}
}
这里加上锁也是不安全的,我们具体分析一下。还是两个线程,当出现这种执行顺序时,
如图:
由图中我们可以知道,这种加锁,仍会 new两个。
在这里我们可以采用双重 if 来解决这种线程安全问题。
如代码:
class SingletonLazy {
private static SingletonLazy instance = null;
public static Object locker = new Object();
public SingletonLazy getinstance(){
if(instance == null){
synchronized (locker){
if(instance == null){
instance = new SingletonLazy();
}
}
}
return instance;
}
}
如代码,我们在锁里面再加个 if 就可以避免 两个new了,使线程安全。