Fork me on GitHub

设计模式———单例模式

设计模式——单例模式
定义:单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例,而且自行实例化并向整个系统提供这个实例

通常单例模式在Java语言中,有两种构建方式:
懒汉方式:指全局的单例实例在第一次被使用时构建。
饿汉方式:指全局的单例实例在类装载时构建。

代码实现:
懒汉式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Singleton implements Serializable 
{
//懒汉式
public volatile static Singleton singleton = null;
//私有构造方法
private Singleton()
{
if(singleton!=null)throw new RuntimeException("该类对象单例模式,不可实例化");
}
//实例方法
public static Singleton getInstance()
{
//判断是否为空
if(singleton==null)
{
//同步
synchronized (Singleton.class)
{
//是否为空
if(singleton==null)
{
singleton = new Singleton();
}
}
}
return singleton;
}
}

理解:一种懒加载的思想,当程序需要这个实例的时候才去创建对象,就如同一个人懒的饿到不行了才去吃东西,synchronized同步锁防止创建多个实例对象使用双重检查进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率又实现了Serializable接口可以被序列化。
为什么判断两次是否为空:外面的判断是为了防止不必要地操作mutex(互斥锁),里面的判断是为了防止多次实例化,外面的singleton==null在临界外,这时如果删除了里面的singleton==null,就会出现以下情景:
线程A判断singleton==null为真,线程B判断singleton==null为真,线程A进入临界区然后实例化singleton,线程A退出临界区;线程B进入临界区然后实例化singleton,线程B退出临界区,所以里面的判断在多线程下是很有必要的,外面的判断虽然不必要,删掉仍然可以保证只实例化一次,但他可以在singleton实例化后避免线程进入临界区,提高性能。

饿汉式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Singleton
{
//饿汉式
private Singletonl() {}
private static Singleton singleton = new Singleton();
public static Singleton getInstance()
{
return singleton ;
}

public void print()
{
System.out.println("测试方法");
}

}

理解:不管程序是否需要这个对象的实例,总是在类加载的时候就先创建好实例,理解起来就像不管一个人想不想吃东西都把吃的先买好,如同饿怕了一样。饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。