设计模式-单例模式和多例模式

abstract

保证对象只能被实例化一次的设计模式称为单例模式。

单例模式

饿汉模式

最简单的实现方法就是,一开始就初始化这个对象,并且将构造方法私有化。

1
2
3
4
5
6
7
8
9
public class Singleton{
private static Singleton singleton = new Singleton();

private Singleton(){}

public static Singleton getInstance(){
return singleton;
}
}

一开始就创建实例的设计方法也成为饿汉模式。

懒汉模式

还可以在调用的时候再初始化,称为懒汉模式。

1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton{
private static Singleton singleton = null;

private Singleton(){}

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

懒,就要付出代价。

基础懒汉模式并不是线程安全的,因为高并发下一个线程判断singleton为空时,会创建一个对象,但是创建对象是需要时间的,如果在创建期间另一个线程执行if判断时,条件成立,也会创建一个对象。对象的属性不变的情况下影响不大,但实例化的时候属性不同时,则有较大影响。

处理办法:

  1. 方法加同步锁。

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

    private static Singleton singleton = null;

    private Singleton(){}

    public synchronized static Singleton getInstance() {
    try {
    if(singleton == null){//懒汉式
    singleton = new Singleton();
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    return singleton;
    }
    }
  1. 可能出现不安全的直接代码使用同步代码块包起来。

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

    private static Singleton singleton = null;

    private Singleton(){}

    public static Singleton getInstance() {
    try {
    if(singleton == null){//懒汉式
    synchronized (Singleton.class) {
    singleton = new Singleton();
    }
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    return singleton;
    }
    }
  1. 使用volatile关键字使线程共用,并进行二次判断。

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

    volatile private static Singleton singleton = null;

    private Singleton(){}

    public static Singleton getInstance() {
    try {
    if(singleton == null){//懒汉式
    synchronized (Singleton.class) {
    if(singleton == null){//二次检查
    singleton = new Singleton();
    }
    }
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    return singleton;
    }
    }

静态内部类

项目启动的时候会优先加载静态资源。

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

private static class Handler{
private static singleton = new Singleton();
}

private Singleton(){}

public Singleton getInstance(){
return Handler.singleton;
}
}

感觉和饿汉模式异曲同工。

静态代码块

静态代码块会被先执行,所以可以使用静态代码块的方式实现单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton{
private static Singleton singleton = null;

private Singleton(){}

static{
singleton = new Singleton();
//init();
}
/** 也可以根据需求绕个远
private static void init(){
singleton = new Singleton();
}
*/
public Singleton getInstance(){
return singleton;
}
}

多例模式