设计模式-单例模式

前言

  在windows系统中,我们可以发现无论我们如何去开启任务管理器,都只能打开一个窗口,因为每个窗口显示的数据,做的功能都是一样的。我们日常的编码中,经常会遇到这样的情况,某个类希望只存在一个实例,这就需要用到 单例模式了

饿汉式

  饿汉式单例模式比较简单。

1
2
3
4
5
6
7
8
9
10
11
public class Singleton{

private static final Singleton instance = Singleton();

private Singleton(){}

public static Singleton getInstance(){
return instance;
}

}

  从上面的代码可以看出,在类加载的时候就会创建Singleton的对象。

懒汉式

  懒汉式单例模式,就是讲对象的实例化放在使用的时候。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton{

private static Singleton instance;

private Singleton(){}

public static Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}

}

  上面这串代码在单线程里面是能够保证只创建一个对象的。但是放到多线程里面就会出现创建多个对象的情况。所以我们如果要创建一个线程安全的单例,则需要加 synchronized 关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton{

private static Singleton instance;

private Singleton(){}

public synchronized static Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}

}

  但是加上同步之后又出现了另外一个性能问题,如果有很多个线程都在请求这个方法,而且这个方法里面要做很多的初始化操作,就会导致其他线程持续等待等情况,下面不使用方法锁的情况,但是需要加双重校验,因为有可能A线程走完第一层的判断后,CPU执行片给了B线程,然后B线程获取锁创建了对象,如果同步代码块里面不添加一层校验就会导致A线程也会创建对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton {

private static Singleton instance;

private Singleton(){}

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}

}

holder模式

  饿汉式没有办法延时加载,而懒汉式的同步在高并发的情况下又会影响性能。那么有没有另外一种方式能够克服这两者的缺点呢?答案肯定是有的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {

private Singleton() {
}

public static Singleton getInstance() {
return Holder.instance;
}

private static class Holder {
private static final Singleton instance = new Singleton();
}

}

  由于静态单例对象没有作为Singleton的成员变量直接实例化,因此类加载时不会实例化Singleton,第一次调用getInstance()时将加载内部类Holder,在该内部类中定义了一个static类型的变量instance,此时会首先初始化这个成员变量,由Java虚拟机来保证其线程安全性,确保该成员变量只能初始化一次。由于getInstance()方法没有任何线程锁定,因此其性能不会造成任何影响。

Kotlin下的单例模式

饿汉式

  kotlin下的饿汉式就有意思了,如下就是一个饿汉式的单例模式。

1
object Singleton

  你没有看错,他就是一个饿汉式,我们通过工具可以看到它对应的java代码如下。

1
2
3
4
5
6
7
8
9
10
11
public final class Singleton {
public static final Singleton INSTANCE;

private Singleton() {
INSTANCE = (Singleton)this;
}

static {
new Singleton();
}
}

懒汉式

  kotlin里面是没有synchronized关键字的,如果要是用同步方法的形式,则需要使用 @Synchronized 注解。而同步代码块的方式是使用 synchronized() 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Singleton private constructor() {

companion object {

private var instance: Singleton? = null

fun getSingleton(): Singleton {
if (instance == null) {
synchronized(Singleton::class.java) {
if (instance == null) {
instance = Singleton()
}
}
}
return instance!!
}

}

}

holder方式

  再来看看holder方式如何通过kotlin来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Singleton private constructor() {

companion object {

fun getSingleton(): Singleton {
return Holder.instance
}

}

private object Holder {
val instance: Singleton = Singleton()
}

}

毒鸡汤

  日子还长,别太失望~

本文标题:设计模式-单例模式

文章作者:严方雄

发布时间:2018-03-05

最后更新:2018-09-13

原始链接:http://yanfangxiong.com/2018/03/05/设计模式-单例模式/

0%