概念:**单例模式指的是不管你去创建多少次对象,对象始终都只有一个。**
这里主要介绍了四种方式
懒汉式:只在第一次调用的时候创建,之后不再创建。
public class SingletonLazy {
private static SingletonLazy singletonLazy = null ;
private String objName ;
private SingletonLazy(){
}
public static SingletonLazy getSingletonLazy(){
//此处线程不安全
if (singletonLazy == null ){
singletonLazy = new SingletonLazy();
}
return singletonLazy;
}
public String getObjName() {
return objName;
}
public void setObjName(String objName) {
this.objName = objName;
}
}
以上代码在标记线程不安全处会发生线程安全问题:
场景:线程1第一次来到标记处,此时singletonLazy 还是为null,所以马上要创建对象,但此时刚好分配的时间片用完,还未执行创建对象。此时线程2进入,应为此时singletonLazy还未创建,所以还是null,所以线程2能去创建对象。线程2创建完对象,然后这时线程1又开始执行了,此时会接着上次执行的代码处执行,即创建一个新的对象,此时就会创建出两个不一样的对象。
饿汉式
在类加载的时候就已经创建了,所以是线程安全的,但是就是消耗资源多。在不需要的时候也存在该对象。
public class SingletonHunger {
private static SingletonHunger singletonHunger = new SingletonHunger();
private SingletonHunger(){}
public static SingletonHunger getSingletonHunger(){
return singletonHunger;
}
}
静态内部类
其实就是在饿汉式的基础上的改进,因为饿汉式会在类加载的时候就创建对象,所以会消耗不必要的内存。所以我们引进内部类来创建对象,因为内部类的静态变量并不会随着外部类加载而创建。同时这个是一个线程安全的创建方式。
public class SingletStaticClass {
SingletStaticClass(){}
private static class InnerClass{
//内部类加载的时候创建
static final SingletStaticClass singletStaticClass = new SingletStaticClass();
}
public static SingletStaticClass getSingletStaticClass(){
return SingletStaticClass.InnerClass.singletStaticClass;
}
}
双检查加锁
是懒汉式改进,因为懒汉式是一个线程不安全的单例模式,所以这里引进锁的方式。其实可以直接写一个同步方法的,但是这样性能太差了,不考虑。因此就在方法内加上锁,但是要又双重判断,不然也是会线程不安全的。
public class SingletDoubleLok {
private static volatile SingletDoubleLok singleton;
private SingletDoubleLok(){}
public static SingletDoubleLok getSingletDoubleLok(){
if (null == singleton){
synchronized (singleton){
if (null == singleton){
singleton = new SingletDoubleLok();
}
}
}
return singleton;
}
}