欢迎转载。请附出处:
http://blog.csdn.net/as02446418/article/details/47952947
单例模式(Singleton)
首先来明白一个问题,那就是在某些情况下,有些对象。我们仅仅须要一个就能够了,
比方,一台计算机上能够连好几个打印机,可是这个计算机上的打印程序仅仅能有一个,
这里就能够通过单例模式来避免两个打印作业同一时候输出到打印机中,
即在整个的打印过程中我仅仅有一个打印程序的实例。
简单说来,单例模式(也叫单件模式)的作用就是保证在整个应用程序的生命周期中,
不论什么一个时刻。单例类的实例都仅仅存在一个(当然也能够不存在)。
单例模式的结构图
从上面的类图中能够看出,在单例类中有一个构造函数 Singleton ,
可是这个构造函数却是私有的(前面是“ - ”符号),
然后在里面还公开了一个 GetInstance()方法,
通过上面的类图不难看出单例模式的特点,从而也能够给出单例模式的定义
单例模式保证一个类仅有一个实例。同一时候这个类还必须提供一个訪问该类的全局訪问点。
以下来看代码:
public class Singleton1 {
private static Singleton1 instance;
private Singleton1(){
System.out.println("我是线程不安全的饿汉singleton");
}
public static Singleton1 getSingleton1(){
if (instance==null) {
instance = new Singleton1();
}
return instance;
}
}
如上面代码所看到的。这样的写法是最不推荐的。也是由于它的线程不安全,我们来看一下測试代码和执行结果:
线程不安全的singleton
public class SingletonTest {
public static void main(String[] args){
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Singleton1.getSingleton1();
}
}).start();
}
}
}
这里new了三个singleton,在多线程环境下可能存在多个线程推断instance==null,所以会分别new出自己的instance,这显然违背了单例模式的初衷。
接下来我们换种写法:
线程安全的饿汉singleton
public class Singleton2 {
private static Singleton2 instance = new Singleton2();
private Singleton2(){
System.out.println("我是线程安全的饿汉singleton");
}
public static Singleton2 getSingleton1(){
return instance;
}
}
以下是执行结果:
为什么说是饿汉的singleton,由于如上面代码所看到的,在用到演示样例instance之前就已经把它初始化好了。尽管这里是线程安全的,可是也会影响性能。所以我们来看第三种singleton。
线程安全的懒汉singleton
public class Singleton {
private Singleton(){
System.out.println("我是线程安全的singleton");
}
private static class singletonHolder{
private final static Singleton instance = new Singleton();
}
public static Singleton getSingleton(){
return singletonHolder.instance;
}
}
以下是执行结果:
如上述代码所看到的,这里用到了singletonHolder这个内部类,这个内部类仅仅会在singletonHolder.instance中用到,也就是用的时候才会初始化,故称为懒汉singleton。这样既攻克了多线程下不安全的问题,同一时候也攻克了提前初始化影响的性能问题,所以是最推荐的一种写法。