1. 什么是单例模式
通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
2. 为什么需要单例模式
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
3. Java中的单例模式——饿汉模式
/**
* 饿汉模式
*/
public class Singleton_1 {
//将构造方法私有化,不允许外界直接创建对象
private Singleton_1(){}
//创建唯一的实例,使用private static修饰
private static Singleton_1 singleton=new Singleton_1();
//提供一个用于获取实例的方法,使用public static修饰
public static Singleton_1 getInstance() {
return singleton;
}
}
4. Java中的单例模式——懒汉模式
/**
* 懒汉模式
*/
public class Singleton_2 {
//将构造方法私有化,不允许外界直接创建对象
private Singleton_2(){}
//声明唯一的实例,使用private static修饰
private static Singleton_2 singleton=null;
//提供一个用于获取实例的方法,使用public static修饰
public static Singleton_2 getInstance() {
if(singleton==null)
singleton=new Singleton_2();
return singleton;
}
}
5. 饿汉模式vs懒汉模式
饿汉模式由于在加载类的时候就创建了对象,所以加载速度较慢,但运行时获取对象速度较快,饿汉模式是线程安全的。
懒汉模式在加载类的时候不创建对象,所以加载速度较快,但在运行时获取对象,所以速度较慢,懒汉模式是线程不安全的。
| 类加载速度 | 运行时获取对象速度 | 线程安全 |
饿汉模式 | 慢 | 快 | 是 |
懒汉模式 | 快 | 慢 | 否 |
6. 解决懒汉模式中的线程不安全
public static Singleton_2 getInstance() {
if(singleton==null)
singleton=new Singleton_2();
return singleton;
}
在多线程编程中,当两个线程同时调用getInstance()方法时,第一个线程执行到第二行,未进入到第三行,第二个线程执行到第二行的时候,发现singleton是null,此时单例模式就失效了。解决办法是给方法加入同步锁:
public static Singleton_2 getInstance() {
if(singleton==null){
synchronized (Singleton_2.class){
if(singleton==null)//双重锁定
singleton=new Singleton_2();
}
}
return singleton;
}