# 单例模式2
# jad 查看枚举的方法定义
public enum EnumInstance {
INSTANCE;
// 这样是全局的
public void print() {
System.out.println("INSTANCE");
}
1
2
3
4
5
6
7
2
3
4
5
6
7
还可以定义抽象方法,每个枚举自己再实现
public enum EnumInstance {
INSTANCE {
@Override
public void print() {
System.out.println("INSTANCE");
}
};
// 这样是全局的
public abstract void print();
private Object data;
public static EnumInstance getInstance() {
return INSTANCE;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
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
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
那么使用 jad 查看这样的写法被编译成什么了
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: EnumInstance.java
package cn.mrcode.newstudy.design.pattern.creational.singleton;
import java.io.PrintStream;
public abstract class EnumInstance extends Enum
{
public static EnumInstance[] values()
{
return (EnumInstance[])$VALUES.clone();
}
public static EnumInstance valueOf(String name)
{
return (EnumInstance)Enum.valueOf(cn/mrcode/newstudy/design/pattern/creational/singleton/EnumInstance, name);
}
private EnumInstance(String s, int i)
{
super(s, i);
}
public abstract void print();
public static EnumInstance getInstance()
{
return INSTANCE;
}
public Object getData()
{
return data;
}
public void setData(Object data)
{
this.data = data;
}
public static final EnumInstance INSTANCE;
private Object data;
private static final EnumInstance $VALUES[];
static
{
INSTANCE = new EnumInstance("INSTANCE", 0) {
public void print()
{
System.out.println("INSTANCE");
}
}
;
$VALUES = (new EnumInstance[] {
INSTANCE
});
}
}
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
可以看到被挪到静态代码块中了。
# 容器单例模式
适合的场景:在初始化的时候把需要的对象 put ;因为现在这个是线程不安全的
public class ContainerSingleton {
private static Map<String, Object> singletonMap = new HashMap<>();
private ContainerSingleton() {
}
public static void putInstance(String key, Object instance) {
if (!singletonMap.containsKey(key)) {
singletonMap.put(key, instance);
}
}
public static Object getInstance(String key) {
return singletonMap.get(key);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ThreadLocal 线程单例模式
public class ThreadLocalInstance {
private ThreadLocalInstance() {
}
private static final ThreadLocal<ThreadLocalInstance> INSTANCE_THREAD_LOCAL
= new ThreadLocal<ThreadLocalInstance>() {
@Override
protected ThreadLocalInstance initialValue() {
return new ThreadLocalInstance();
}
};
public static ThreadLocalInstance getInstance() {
return INSTANCE_THREAD_LOCAL.get();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
测试
@Test
public void test9() {
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
}).start();
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
System.out.println(Thread.currentThread().getName() + " ====== " + ThreadLocalInstance.getInstance());
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
输出
main ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@1d16f93d
main ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@1d16f93d
main ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@1d16f93d
main ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@1d16f93d
Thread-0 ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@3187be8a
Thread-0 ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@3187be8a
Thread-0 ====== cn.mrcode.newstudy.design.pattern.creational.singleton.ThreadLocalInstance@3187be8a
1
2
3
4
5
6
7
2
3
4
5
6
7
可以看到,在同一个线程中的对象是唯一的。
# 单例模式在其他代码中的应用
java.lang.Runtime#getRuntime 就是一个恶汉式的单例模式
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
1
2
3
4
5
2
3
4
5
java.awt.Desktop#getDesktop
public static synchronized Desktop getDesktop(){
if (GraphicsEnvironment.isHeadless()) throw new HeadlessException();
if (!Desktop.isDesktopSupported()) {
throw new UnsupportedOperationException("Desktop API is not " +
"supported on the current platform");
}
sun.awt.AppContext context = sun.awt.AppContext.getAppContext();
Desktop desktop = (Desktop)context.get(Desktop.class);
// 同步方法,先从类似容器的上下文中获取对象,没有的时候在创建一个
if (desktop == null) {
desktop = new Desktop();
context.put(Desktop.class, desktop);
}
return desktop;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17