设计模式-单例模式

单例模式

单例模式属于最常用也比较简单,基本有几种写法。

无并发

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {
//一个静态的实例
private static Singleton singleton;
//私有化构造函数
private Singleton(){}
//给出一个公共的静态方法返回一个单一实例
public static Singleton getInstance(){
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}

上面无并发的单列模式写出了单例模式的几个基本的条件:

1、构造函数私有的,即不允许从外部实例化对象。

2、用static关键字修饰类实例。

3、提供一个返回改单例对象的方法,上面采用的是“饿汉”式加载,即用到时才返回。

双重加锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SynchronizedSingleton {
//一个静态的实例
private static SynchronizedSingleton synchronizedSingleton;
//私有化构造函数
private SynchronizedSingleton(){}
//给出一个公共的静态方法返回一个单一实例
public static SynchronizedSingleton getInstance(){
if (synchronizedSingleton == null) {
synchronized (SynchronizedSingleton.class) {
if (synchronizedSingleton == null) {
synchronizedSingleton = new SynchronizedSingleton();
}
}
}
return synchronizedSingleton;
}
}

有并发时可以采用上面这种加锁的方式,但是用于jvm不限制操作系统重排序,所以可能在并发时还是有可能会出现有的线程请求时只分配了地址却没有初始化过的对象。

利用JVM强制同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {
private Singleton(){}
public static Singleton getInstance(){
return SingletonInstance.instance;
}
private static class SingletonInstance{
static Singleton instance = new Singleton();
}
}

由于jvm会保证一个类的静态属性只会在第一次加载类时初始化,所以我们无需担心初始化到一半时别的线程会使用到这个变量。

坚持原创技术分享,您的支持将鼓励我继续创作!

热评文章