#单例模式
单例模式是java中最简单的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
单利模式的特点
- 构造方法私有化
- 提供一个返回单例对象本身的公共方法
- 提供一个静态的私有变量
单例模式分懒汉式和饿汉式
饿汉式
饿汉式在程序运行时加载,比较占内存空间
class Singleton{
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
或者
class Singleton1 {
private static Singleton1 instance;
static {
instance = new Singleton1();
}
public static Singleton1 getInstance() {
return instance;
}
}
懒汉式
懒汉式在需要的时候加载,即第一次实例化的时候加载
class Singleton2 {
private static Singleton2 instance;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
上诉为最简单的懒汉式,但是这种方法线程不安全
假设有两个线程,线程A和线程B,线程A实例化Singleton2时在if(instance == null)判断后中断,然后线程B也开始执行 if(instance == null),这个时候,instance还是null,判定为真,这时,A和B都实例化了Singleton2,创建了两个Singleton2的实例化对象
我们用代码测试一下
新建一个类,用于实例化Singleton2,并输出地址
class temp extends Thread {
@Override
public void run() {
Singleton2 singleton = Singleton2.getInstance();
System.out.println(singleton);
}
}
然后测试
public static void main(String[] args) {
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
new Thread(new temp()).start();
}
执行结果为
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@5ec1d90c
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@4c6aca09
Test.Singleton2@73248cf9
Test.Singleton2@52a17671
Test.Singleton2@73248cf9
运行结果出现了多个地址,所以该方法线程不安全
既然线程不安全,我们就对该方法加锁
class Singleton3{
private static Singleton3 instance;
private Singleton3() {
}
public synchronized static Singleton3 getInstance() {
if (instance == null) {
instance = new Singleton3();
}
return instance;
}
}
加锁之后,线程安全的问题就解决了,但新的问题又来了,因为对方法进行加锁,所以当一个线程运行该代码时,另一个线程就只能处于等待状态,大大降低了效率,所以又对该方法进行改进,把锁改为锁代码块儿
class Singleton4 {
private static Singleton4 instance;
private Singleton4() {
}
public static Singleton4 getInstance() {
if (instance == null) {
synchronized (Singleton4.class) {
if (instance == null)
instance = new Singleton4();
}
}
return instance;
}
}