一,缘由
暑假就要去实习了,有点慌张。以前学Java时有许多重要的知识点都存在doc文档,心想什么时候有时间就写到博客里,结果可想而知,文档全都归西了,今年才开始静的下心来写博客。好吧,既然那些文档不见了,那就隔几天写一篇博客,就当是重温自己的Java之路吧。既然是重温Java,首当其冲的当然就是设计模式了。那么就从Java单例模式开始吧。
二,单例模式的分类
有没搞错,单例模式还有分类?还真有,单例模式按其特点来分就有两种,一是饿汉模式,另一种就是懒汉模式。
三,单例模式之饿汉模式
饿汉模式的特点:只要类一加载,就会创建对象。贴一段代码吧,不然不太好描述,嘻嘻!
package com.bighuan.singleton;
/**
* 单例模式之饿汉式
* 特点:类一加载就创建对象
*
* @author bighuan JDK中的单例体现:Runtime runtime=Runtime.getRuntime();
*/
public class SingletonPad {
private static SingletonPad mInstance = new SingletonPad();
// 把构造方法私有是为了不让外界随意创建
private SingletonPad() {
}
public static SingletonPad getInstance() {
return mInstance;
}
public void show() {
System.out.println("卖平板1了...");
}
}
不管是哪种单例模式,都是为了只有一个实例对象,对象不能被外界随意创建。所以就把构造方法私有private了,只能在该类内部new对象。并且在类被加载的时候就创建了一个对象(mInstance用static修饰了),该对象是私有的就保证mInstance不会被别人置为null,若没有private修饰,就有可能发生SingletonPad.mInstace=null,那就尴尬了。程序内提供了一个静态的getInstance()公共方法,以便获得SingletonPad对象。至于为什么叫做饿汉模式,那是因为这个SingletonPad类只要被加载了,就会创建一个对象,就像饿汉一样,什么都吃。如果我们用不到这个对象,那就浪费了资源了,因为多创建了对象啊。所以,就有了单例模式之懒汉模式。
四,单例模式之懒汉模式
懒汉模式的特点:什么时候用就什么时候创建对象。不多说,贴代码再解释。
package com.bighuan.singleton;
/**
* 设计模式之懒汉式
* 特点:什么时候用就什么时候创建
*
* @author bighuan
*
*/
public class SingletonPad2 {
private volatile static SingletonPad2 mInstance = null;
private SingletonPad2() {
}
/**
* 如果不加锁,则会有线程安全问题
*
* @return
*/
public static SingletonPad2 getInstance() {
// 双重锁定(Double-Check Locking),第一次创建对象时会受到同步锁的影响,但只要创建过一次,就不会再受到同步锁的影响了。
if (mInstance == null) {
synchronized (SingletonPad2.class) {
if (mInstance == null) {
mInstance = new SingletonPad2();
}
}
}
return mInstance;
}
public void show() {
System.out.println("卖平板2了...");
}
}
懒汉模式和饿汉模式的区别就是,懒汉模式不会再加载类的时候就创建一个对象,而是什么时候要用什么时候就创建。并且,特别要注意的是,如果懒汉模式的getInstance()方法内部不加锁的话,是会有线程安全问题的(注意看我代码中的注释)。当然了,同步锁也可以加在getInstance()方法上,但那样就会影响性能,因为那样的话每次调用那个方法都会受到同步锁的影响,从而影响效率。所以在方法内部加锁就足够了,同步锁最多只会使用一次。
另外,需要注意的时,我们在声明mInstace时使用了一个volatile关键字。volatile是一个类型修饰符,volatile用来修饰被不同线程访问和修改的变量。如果我们在懒汉模式中不加这个关键字,是有问题的。具体原因我就不解释了,看客就自行百度了。
五,测试
很简单,看代码及结果:
package com.bighuan.singleton;
/**
* 测试单例模式
*
* @author bighuan
*
*/
public class SingletonTest {
public static void main(String[] args) {
// 测试单例模式之饿汉模式
SingletonPad pad1 = SingletonPad.getInstance();
SingletonPad pad2 = SingletonPad.getInstance();
pad1.show();
pad2.show();
System.out.println(pad1 == pad2);
System.out.println("------------");
// 测试单例模式之懒汉汉模式
SingletonPad2 p1 = SingletonPad2.getInstance();
SingletonPad2 p2 = SingletonPad2.getInstance();
p1.show();
p2.show();
System.out.println(p1 == p2);
}
}
运行结果如下:
卖平板1了...
卖平板1了...
true
------------
卖平板2了...
卖平板2了...
true
确实只有一个对象吧,哈哈!
六,总结
面试时考官喜欢在懒汉模式的线程安全问题上做文章,但只要理解了单例模式,就完全没问题的!