在Java语言中,无论是jdk还是各类框架都会运用到许多单例模式。
1、何为单例模式?
我们都知道,面向对象语言中创建对象是需要消耗内存资源的,而有时候有的类仅需一个对象,为了确保这个类在程序中仅有一个对象而设计出来的模式叫做单例模式。
单例模式的特点
1、构造器私有化:Java中,如果没有重载一个类的构造器,这个类会有一个默认无参的构造器。而且这个构造器的的权限是public的。为了限制该类的对象数量,所以在单例模式中要将这个类的构造方法写为private。
2、有一个自己类型本身的静态属性:当构造器私有化时,其他类就不能创建该类对象,必须要通过自己本身返回一个对象,所以要有一个自己的类型,而且要能通过类名访问到,所以要用static修饰。
3、对外提供一个获取实例的静态方法:这个同上,是一个创建其该实例的方法,一般方法名为getInStance,返回值为该类型的一个实例。
2、单例模式的种类
饿汉式
先看代码
public class SingletonDemo {
private static SingletonDemo singletonDemo = new SingletonDemo(); //有个自己本身类型的属性
private SingletonDemo(){} //构造器私有化
public static SingletonDemo getInStance(){//一个对外提供返回该对象的方法
return singletonDemo;
}
}
上面代码中,getInStance()方法是返回singletonDemo对象,但是singletonDemo这个对象在类加载时就已经创建了,可以看出饿汉式的特点是无论是否需要用到该对象。都会先创建出来。
懒汉式
public class SingletonDemo {
private static SingletonDemo singletonDemo; //有个自己本身类型的属性
private SingletonDemo() {
} //构造器私有化
public static SingletonDemo getInStance() {//一个对外提供返回该对象的方法
if (singletonDemo == null) {
singletonDemo = new SingletonDemo();
}
return singletonDemo;
}
}
从上不难看出,懒汉式和饿汉式的区别是创建对象的时机不一样。懒汉式创建对象是在getInStance()方法里面,也就是只有需要用到该对象时才会去创建。
在日常开发中,这两种模式一般更推荐使用饿汉式,因为懒汉式在多线程环境中有可能不止一个线程在同一时刻都调用getInStance()方法,如果刚好在那个时刻singletonDemo也还没有创建出来,那么就会出现两个以上的对象,就不符合单例模式
双重锁模式
在前面两种模式中,
饿汉式 因为无论需不需要用到都会先创建对象,所以会产生一些内存垃圾。
懒汉式 在多线程中线程不安全。
所以又有了 双重锁模式
public class SingletonDemo {
private static SingletonDemo singletonDemo; //有个自己本身类型的属性
private SingletonDemo() {
} //构造器私有化
public static SingletonDemo getInStance() {//一个对外提供返回该对象的方法
if (singletonDemo == null) {//第一次判断
synchronized (SingletonDemo.class){//加锁,确定只有一个线程进来
if (singletonDemo == null){//第二次判断
singletonDemo = new SingletonDemo();
}
}
}
return singletonDemo;
}
}
可以看出双重锁模式是懒汉式的升级版。懒汉式因为线程不安全,所以双重锁模式在懒汉式的基础下加上同步锁,多一次判断解决了线程不安全的问题。