单线程

四季春风,不厌冬

  1. java单例bean
    1. 饿汉式
    2. 懒汉式(DCL)
    3. 内部类
  2. Spring单例模式

  最早学习java的时候,还没有接触“单例”,直到学了Spring,才知道了单例模式和原型模式。首先来看看java原生态的单例bean。   

java单例bean

饿汉式

  饥不可耐,项目启动完成时,单例bean已经生成。

  • 单例bean
1
2
3
4
5
6
7
8
9
10
11
12
public class SingleInstance {

private static final SingleInstance INSTANCE = new SingleInstance();

private SingleInstance() {

}

public static SingleInstance getInstance() {
return INSTANCE;
}
}
  • 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class RunTest {

public static void main(String[] args) {

for (int i = 0; i < 3; i++) {

new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ":" + SingleInstance.getInstance().hashCode());
// System.out.println(Thread.currentThread().getName() + ":" + SingleInstance2.getInstance().hashCode());
// System.out.println(Thread.currentThread().getName() + ":" + SingleInstance3.getInstance().hashCode());
}).start();
}
}
}

  上述每个线程输出的hashCode值相同,说明bean为单例。   

懒汉式(DCL)

  能少做便少做,项目启动时只是声明对象引用,直到真正发起调用时,系统才为其创建对象。避免资源占用。  

  • 单例bean
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 SingleInstance2 {

private volatile static SingleInstance2 INSTANCE;

private SingleInstance3() {

}

public static SingleInstance2 getInstance() {

if (null == INSTANCE) {
/*
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
synchronized (SingleInstance2.class) {
if (null == INSTANCE) {
INSTANCE = new SingleInstance2();
}
}
}

return INSTANCE;
}
}

  测试类输出的hasCode也是相同的,说明bean为单例。

内部类

  利用jvm类加载时,加锁阻塞的原理,保证只有一个线程能获得锁,达到单例bean效果,并且继承了懒汉式的优点——延迟加载,不占用资源。   

  • 单例bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SingleInstance3 {

/**
* jvm加载外部类时,不会加载内部类,即启动时,不会多占用内存资源
*/
public static class MySingleInstance {

private static SingleInstance3 INSTANCE = new SingleInstance3();
}

private SingleInstance3() {

}

/**
* invoke时,加载内部类,即延时加载(不主动加锁的懒汉模式)
* 本质:利用jvm类加载加锁阻塞原理,保证只有一个线程能获得锁(创建一个实例)
*/
public static SingleInstance3 getInstance() {
return MySingleInstance.INSTANCE;
}
}

  测试类输出的hasCode也是相同的,说明bean为单例。

Spring单例模式

本文作者 : pengqin.zhou
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://www.zhoupq.com/blog/%E4%BB%8E%E5%88%9B%E5%BB%BAJava%E5%8D%95%E4%BE%8BBean%EF%BC%8C%E5%88%B0%E5%AD%A6%E4%B9%A0Spring%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/

本文最后更新于 天前,文中所描述的信息可能已发生改变