一. 定义及概念

1. 单例模式是Java中一种常见的设计模式,用于确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

2. 单例设计模式有以下三个特点:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

3.  在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印

机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被

两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

4. 单例设计模式的组成要素

     ① 私有的构造方法

② 指向自己实例的静态引用

③ 以自己实例为返回值的公有方法

二. 分类说明

单例设计模式根据实例化对象时机的不同,又分为三种: ①饿汉式单例  ②懒汉式单例  ③登记式单例。

① 饿汉式单例 

public class Singleton {
	// 组成元素1:指向自己实例的私有静态引用
	private static final Singleton singleton = new Singleton();

	// 组成元素2: 私有的构造方法
	private Singleton() {
	}

	// 组成元素3:以自己实例为返回值的静态的公有的方法
	public static Singleton getInstance() {
		return singleton;
	}
}

饿汉式在类初始化加载的同时(而不是实例化时)已经创建好一个静态的对象供系统使用,以后不再改变。

问题1:私有构造方法?

将构造方法限定为private,可以防止类在外部被实例化,也就是说,单例类的唯一实只能通过该实例类中方法

得到(getInstance())。

问题2:线性安全?

是的!

②  懒汉式单例

public class Singleton {
	// 组成元素1:指向自己实例的私有静态引用
	private static Singleton singleton;

	// 组成元素2: 私有的构造方法
	private Singleton() {
	}

	// 组成元素3:以自己实例为返回值的静态的公有的方法
	public static Singleton getInstance() {
		if(singleton==null){  
            singleton = new Singleton();  
        }  
		return singleton;
	}
}

  懒汉式单例在调用取得实例方法(getInstance()方法)时才会实例化对象,所以也可以用延迟加载来表示其特点。

与饿汉式不同,懒汉式在多线程下可能会出现安全问题,即可能出现多个Singleton实例,所以我们需要一些措施来保证线程安全。

方法1:  在getInstance方法上加同步

public static synchronized Singleton getInstance() {

if (single == null) {

single = new Singleton(); 

}

return single; 

}

这种方法虽然解决了线程安全问题,但当有多个线程访问就需要频繁判断锁,性能不是太高。

所以有了改进的第二种方法。

 

方法2:双重检查锁定

public static Singleton getInstance() {

if (singleton == null) { 

synchronized (Singleton.class) {

if (singleton == null) {

singleton = new Singleton(); 

}

}

}

}

 

三. 各方法的优缺点

1. 懒汉式以及饿汉式的区别

饿汉就是类一旦加载,就把单例初始化完成,保证在getInstance时,单例已经存在

而懒汉比较懒,只有调用getInstance时,才初始化实例。

1.线程安全

饿汉式天生线程安全,可以直接使用多线程而不会出现问题

懒汉式本身线程非安全,可以按照上面两种方法改造实现线程安全

2. 资源加载与性能

饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在

第一次调用时速度也会更快,因为其资源已经初始化完成。

而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的

工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

2.单例模式的优点

1.在内存中只有一个对象,节省内存空间

2.避免频繁的创建和销毁对象,提高性能

3.避免对共享资源的多重占用

4.可以进行全局访问

四. 总结

一般在Java中,比较常用的是饿汉式,因为天然线程安全。但懒汉式的各个特点及变形线程安全依然要掌握。