设计模式之单例模式

释放双眼,带上耳机,听听看~!

设计模式之单例模式

应用场景:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

模式分析

Spring 中的单例模式完成了后半句话,即提供了全局的访问点 BeanFactory。但没有从构造器级别去
控制单例,这是因为 Spring 管理的是是任意的 Java 对象。 Spring 下默认的 Bean 均为单例。

设计模式之单例模式

常用单例模式写法:饿汉式、懒汉式、注册式、序列化。

设计模式之单例模式

代码演示:

饿汉式单例模式


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1/**
2 *  饿汉式单例模式
3 */
4// 它是在类加载的时候就立即初始化,并且创建单例对象
5//优点:没有加任何的锁、执行效率比较高,
6//在用户体验上来说,比懒汉式更好
7//缺点:类加载的时候就初始化,不管你用还是不用,我都占着空间
8//浪费了内存,有可能占着茅坑不拉屎
9//绝对线程安全,在线程还没出现以前就是实例化了,不可能存在访问安全问题
10public class Hungry {
11    private Hungry(){};
12    // 加载顺序:
13    //先静态、后动态
14    //先属性、后方法
15    //先上后下
16    private static final Hungry hungry=new Hungry();
17    public static  Hungry getInstance(){
18        return hungry;
19    }
20}
21
22
23

懒汉式测试


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
1public class HungryTest {
2
3    @Test
4    public void getInstance() {
5        int count = 200;
6
7        //发令枪,我就能想到运动员
8        final CountDownLatch latch = new CountDownLatch(count);
9
10        long start = System.currentTimeMillis();
11        for (int i = 0; i < count;i ++) {
12            new Thread(){
13                @Override
14                public void run() {
15                    try{
16
17                        try {
18                            // 阻塞
19                            // count = 0 就会释放所有的共享锁
20                            // 万箭齐发
21                            latch.await();
22                        }catch(Exception e){
23                            e.printStackTrace();
24                        }
25
26                        //必然会调用,可能会有很多线程同时去访问getInstance()
27                        Object obj = LazyOne.getInstance();
28                        System.out.println(System.currentTimeMillis() + ":" + obj);
29
30                    }catch (Exception e){
31                        e.printStackTrace();
32                    }
33                }
34            }.start(); //每循环一次,就启动一个线程,具有一定的随机性
35
36            //每次启动一个线程,count --
37            latch.countDown();
38
39        }
40        long end = System.currentTimeMillis();
41        System.out.println("总耗时:" + (end - start));
42        /**
43         *  输出:
44         *  总耗时:34
45         * 1564454351821:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@4e32a067
46         * 1564454351820:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@4e32a067
47         */
48    }
49}
50
51

懒汉式单例

第一版


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1/**
2 *  懒汉式单例(线程不安全)
3 */
4//在外部需要使用的时候才进行实例化
5public class LazyOne {
6    private LazyOne(){}
7    //静态块,公共内存区域
8    private static LazyOne lazyOne=null;
9    public static LazyOne  getInstance(){
10        //调用方法之前,先判断
11        //如果没有初始化,将其进行初始化,并且赋值
12        //将该实例缓存好
13        if (lazyOne==null) {
14            //两个线程都会进入这个if里面
15            lazyOne = new LazyOne();
16        }
17        //如果已经初始化,直接返回之前已经保存好的结果
18        return lazyOne;
19    }
20
21}
22
23
24

测试:


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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
1@Test
2    public void getInstance() {
3        int count = 200;
4
5        //发令枪,我就能想到运动员
6        final CountDownLatch latch = new CountDownLatch(count);
7
8        long start = System.currentTimeMillis();
9        for (int i = 0; i < count;i ++) {
10            new Thread(){
11                @Override
12                public void run() {
13                    try{
14
15                        try {
16                            // 阻塞
17                            // count = 0 就会释放所有的共享锁
18                            // 万箭齐发
19                            latch.await();
20                        }catch(Exception e){
21                            e.printStackTrace();
22                        }
23
24                        //必然会调用,可能会有很多线程同时去访问getInstance()
25                        Object obj = LazyOne.getInstance();
26                        System.out.println(System.currentTimeMillis() + ":" + obj);
27
28                    }catch (Exception e){
29                        e.printStackTrace();
30                    }
31                }
32            }.start(); //每循环一次,就启动一个线程,具有一定的随机性
33
34            //每次启动一个线程,count --
35            latch.countDown();
36
37        }
38        long end = System.currentTimeMillis();
39        System.out.println("总耗时:" + (end - start));
40        /**
41         *  输出:
42         *  1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@40f54609
43         * 1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
44         * 1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
45         * 1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
46         * 1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
47         * 1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
48         * 1564455011197:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
49         * 1564455011198:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
50         * 1564455011198:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
51         * 1564455011198:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
52         * 1564455011198:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
53         * 1564455011198:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
54         * 1564455011198:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
55         * 1564455011199:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
56         * 1564455011199:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
57         * 1564455011199:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
58         * 1564455011199:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
59         * 1564455011199:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
60         * 1564455011199:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
61         * 1564455011200:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
62         * 1564455011200:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
63         * 1564455011201:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
64         * 1564455011204:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
65         * 1564455011204:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
66         * 1564455011204:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
67         * 1564455011204:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
68         * 1564455011206:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
69         * 1564455011206:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
70         * 1564455011208:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
71         * 1564455011211:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
72         * 1564455011211:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
73         * 1564455011211:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
74         * 1564455011212:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
75         * 1564455011212:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
76         * 1564455011212:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
77         * 1564455011212:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
78         * 1564455011212:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
79         * 1564455011213:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
80         * 1564455011213:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
81         * 1564455011213:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
82         * 1564455011285:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
83         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
84         * 1564455011285:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
85         * 1564455011285:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
86         * 1564455011285:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
87         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
88         * 1564455011286:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
89         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
90         * 1564455011288:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
91         * 1564455011288:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
92         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
93         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
94         * 1564455011290:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
95         * 1564455011291:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
96         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
97         * 1564455011293:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
98         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
99         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
100         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
101         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
102         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
103         * 1564455011294:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
104         * 1564455011294:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
105         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
106         * 1564455011294:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
107         * 1564455011295:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
108         * 1564455011295:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
109         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
110         * 1564455011295:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
111         * 1564455011295:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
112         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
113         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
114         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
115         * 1564455011298:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
116         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
117         * 1564455011299:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
118         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
119         * 1564455011299:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
120         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
121         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
122         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
123         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
124         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
125         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
126         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
127         * 1564455011284:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
128         * 1564455011276:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
129         * 1564455011276:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
130         * 1564455011276:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
131         * 1564455011276:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
132         * 1564455011276:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
133         * 1564455011276:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
134         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
135         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
136         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
137         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
138         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
139         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
140         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
141         * 1564455011275:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
142         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
143         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
144         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
145         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
146         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
147         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
148         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
149         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
150         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
151         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
152         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
153         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
154         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
155         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
156         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
157         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
158         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
159         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
160         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
161         * 1564455011274:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
162         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
163         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
164         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
165         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
166         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
167         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
168         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
169         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
170         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
171         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
172         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
173         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
174         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
175         * 1564455011273:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
176         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
177         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
178         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
179         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
180         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
181         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
182         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
183         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
184         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
185         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
186         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
187         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
188         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
189         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
190         * 1564455011269:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
191         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
192         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
193         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
194         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
195         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
196         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
197         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
198         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
199         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
200         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
201         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
202         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
203         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
204         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
205         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
206         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
207         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
208         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
209         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
210         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
211         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
212         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
213         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
214         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
215         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
216         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
217         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
218         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
219         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
220         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
221         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
222         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
223         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
224         * 1564455011268:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
225         * 总耗时:39
226         * 1564455011267:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
227         * 1564455011213:com.wondersgroup.jg.sscl.singleton.lazy.LazyOne@8623f87
228         *
229         */
230    }
231
232

第二版


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1public class LazyTwo {
2    private LazyTwo(){}
3
4    private static LazyTwo lazy = null;
5
6    /**
7     *  添加了同步锁,但是会有性能损耗
8     */
9    public static synchronized LazyTwo getInstance(){
10
11        if(lazy == null){
12            lazy = new LazyTwo();
13        }
14        return lazy;
15
16    }
17}
18
19

测试


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1 @Test
2    public void getInstance() {
3        long start = System.currentTimeMillis();
4        for (int i = 0; i < 200000000;i ++) {
5            Object obj = LazyTwo.getInstance();
6        }
7        long end = System.currentTimeMillis();
8        System.out.println("总耗时:" + (end - start));
9        /**
10         *  输出:
11         *  总耗时:5892
12         */
13    }
14
15

最终版


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
1//懒汉式单例
2//特点:在外部类被调用的时候内部类才会被加载
3//内部类一定是要在方法调用之前初始化
4//巧妙地避免了线程安全问题
5
6//这种形式兼顾饿汉式的内存浪费,也兼顾synchronized性能问题
7//完美地屏蔽了这两个缺点
8//史上最牛B的单例模式的实现方式
9public class LazyThree {
10
11    private static boolean initialized = false;
12    //默认使用LazyThree的时候,会先初始化内部类
13    //如果没使用的话,内部类是不加载的
14    private LazyThree(){
15        // 防止外部对单例使用反射多次初始化
16        synchronized (LazyThree.class){
17            if(initialized == false){
18                initialized = !initialized;
19            }else{
20                throw new RuntimeException("单例已被侵犯");
21            }
22        }
23    };
24
25    //每一个关键字都不是多余的
26    //static 是为了使单例的空间共享
27    // final保证这个方法不会被重写,重载
28    public static final LazyThree getInstance(){
29        //在返回结果以前,一定会先加载内部类
30        return LazyHolder.LAZY_THREE;
31    }
32
33
34    // 默认不加载
35    private static class LazyHolder{
36        private static final LazyThree LAZY_THREE=new LazyThree();
37    }
38}
39
40
41

测试


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
1@Test
2    public void getInstance() {
3        try{
4
5            //很无聊的情况下,进行破坏
6            Class<?> clazz = LazyThree.class;
7
8
9            //通过反射拿到私有的构造方法
10            Constructor c = clazz.getDeclaredConstructor(null);
11            //强制访问,强吻,不愿意也要吻
12            c.setAccessible(true);
13
14            //暴力初始化
15            Object o1 = c.newInstance();
16
17
18            //调用了两次构造方法,相当于new了两次
19            //犯了原则性问题,
20            Object o2 = c.newInstance();
21
22            System.out.println(o1 == o2);
23//            Object o2 = c.newInstance();
24
25        }catch (Exception e){
26            e.printStackTrace();
27        }
28
29        /**
30         *  输出:
31         *  java.lang.reflect.InvocationTargetException
32  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
33  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
34  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
35  at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
36  at com.wondersgroup.jg.sscl.singleton.lazy.LazyThreeTest.getInstance(LazyThreeTest.java:30)
37  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
38  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
39  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
40  at java.lang.reflect.Method.invoke(Method.java:498)
41  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
42  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
43  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
44  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
45  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
46  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
47  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
48  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
49  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
50  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
51  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
52  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
53  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
54  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
55  at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
56  at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
57  at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
58  at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
59Caused by: java.lang.RuntimeException: 单例已被侵犯
60  at com.wondersgroup.jg.sscl.singleton.lazy.LazyThree.<init>(LazyThree.java:22)
61  ... 27 more
62         */
63
64    }
65
66

注册登记式单例模式


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
1// 注册登记式单例模式
2public class RegisterMap {
3
4    private RegisterMap(){}
5    // 创建并发安全的map集合用了存储被初始化的单例
6    private static Map<String,Object> register = new ConcurrentHashMap<String,Object>();
7
8    // 使用类名获取RegisterMap的单例对象
9    public static RegisterMap getInstance(String name){
10        if(name == null){
11            name = RegisterMap.class.getName();
12        }
13
14        if(register.get(name) == null){
15            try {
16                register.put(name, new RegisterMap());
17            }catch(Exception e){
18                e.printStackTrace();
19            }
20
21        }
22        return (RegisterMap)register.get(name);
23    }
24}
25
26
27

这种注册式单例在spring中的使用


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
1//Spring中的做法,就是用这种注册式单例
2public class BeanFactory {
3    private BeanFactory(){}
4    //线程安全
5    private static Map<String,Object> ioc = new ConcurrentHashMap<String,Object>();
6
7    public static Object getBean(String name){
8        if (!ioc.containsKey(name)){
9            Object put = null;
10            try {
11                put = ioc.put(name, Class.forName(name).newInstance());
12                return put;
13            } catch (InstantiationException e) {
14                e.printStackTrace();
15            } catch (IllegalAccessException e) {
16                e.printStackTrace();
17            } catch (ClassNotFoundException e) {
18                e.printStackTrace();
19            }
20            return put;
21        }else {
22            return ioc.get(name);
23        }
24    }
25}
26
27
28

注册登记单例测试


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
1@Test
2    public void getBean() {
3        int count = 200;
4
5        //发令枪,我就能想到运动员
6        final CountDownLatch latch = new CountDownLatch(count);
7
8        long start = System.currentTimeMillis();
9        for (int i = 0; i < count;i ++) {
10            new Thread(){
11                @Override
12                public void run() {
13                    try{
14
15                        try {
16                            // 阻塞
17                            // count = 0 就会释放所有的共享锁
18                            // 万箭齐发
19                            latch.await();
20                        }catch(Exception e){
21                            e.printStackTrace();
22                        }
23
24                        //必然会调用,可能会有很多线程同时去访问getInstance()
25                        Object obj = BeanFactory.getBean("com.wondersgroup.jg.sscl.singleton.register.Pojo");;
26                        System.out.println(System.currentTimeMillis() + ":" + obj);
27
28                    }catch (Exception e){
29                        e.printStackTrace();
30                    }
31                }
32            }.start(); //每循环一次,就启动一个线程,具有一定的随机性
33
34            //每次启动一个线程,count --
35            latch.countDown();
36
37        }
38        long end = System.currentTimeMillis();
39        System.out.println("总耗时:" + (end - start));
40        // 输出:总耗时:25
41    }
42
43

枚举单例模式


1
2
3
4
5
6
7
8
9
10
1/**
2 *  枚举单例模式
3 */
4public enum  RegiterEnum {
5    INSTANCE,BLACK,WHITE;
6    public void getInstance(){}
7}
8
9
10

生活举例,颜色单例枚举


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1//常量中去使用,常量不就是用来大家都能够共用吗?
2//通常在通用API中使用
3public enum  Color {
4    RED(){
5        private int r = 255;
6        private int g = 0;
7        private int b = 0;
8
9    },BLACK(){
10        private int r = 0;
11        private int g = 0;
12        private int b = 0;
13    },WHITE(){
14        private int r = 255;
15        private int g = 255;
16        private int b = 255;
17    };
18}
19
20

测试


1
2
3
4
5
6
7
8
9
1public class ColorTest {
2    public static void main(String[] args) {
3        System.out.println(Color.RED);
4        // 输出:RED
5    }
6
7}
8
9

反序列化时导致单例破坏


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
1//反序列化时导致单例破坏
2public class Seriable  implements Serializable {
3
4    //序列化就是说把内存中的状态通过转换成字节码的形式
5    //从而转换一个IO流,写入到其他地方(可以是磁盘、网络IO)
6    //内存中状态给永久保存下来了
7
8    //反序列化
9    //讲已经持久化的字节码内容,转换为IO流
10    //通过IO流的读取,进而将读取的内容转换为Java对象
11    //在转换过程中会重新创建对象new
12    public  final static Seriable INSTANCE = new Seriable();
13    private Seriable(){}
14
15    public static  Seriable getInstance(){
16        return INSTANCE;
17    }
18
19    // 告诉jvm转换过程中会继续使用原先的这个对象
20    private  Object readResolve(){
21        return  INSTANCE;
22    }
23}
24
25
26

1
2
3
4
5
6
1
2public class Pojo {
3}
4
5
6

测试


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
1@Test
2    public void getInstance() {
3        Seriable s1 = null;
4        Seriable s2 = Seriable.getInstance();
5
6        FileOutputStream fos = null;
7        try {
8            fos = new FileOutputStream("Seriable.obj");
9            ObjectOutputStream oos = new ObjectOutputStream(fos);
10            oos.writeObject(s2);
11            oos.flush();
12            oos.close();
13
14
15            FileInputStream fis = new FileInputStream("Seriable.obj");
16            ObjectInputStream ois = new ObjectInputStream(fis);
17            s1 = (Seriable)ois.readObject();
18            ois.close();
19
20            System.out.println(s1);
21            System.out.println(s2);
22            System.out.println(s1 == s2);
23
24        } catch (Exception e) {
25            e.printStackTrace();
26        }
27        /**
28         *   输出:
29         *   com.wondersgroup.jg.sscl.singleton.seriable.Seriable@20fa23c1
30         * com.wondersgroup.jg.sscl.singleton.seriable.Seriable@20fa23c1
31         * true
32         */
33    }
34
35

bjectOutputStream(fos);
oos.writeObject(s2);
oos.flush();
oos.close();


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1        FileInputStream fis = new FileInputStream("Seriable.obj");
2        ObjectInputStream ois = new ObjectInputStream(fis);
3        s1 = (Seriable)ois.readObject();
4        ois.close();
5
6        System.out.println(s1);
7        System.out.println(s2);
8        System.out.println(s1 == s2);
9
10    } catch (Exception e) {
11        e.printStackTrace();
12    }
13    /**
14     *   输出:
15     *   com.wondersgroup.jg.sscl.singleton.seriable.Seriable@20fa23c1
16     * com.wondersgroup.jg.sscl.singleton.seriable.Seriable@20fa23c1
17     * true
18     */
19}
20
21

给TA打赏
共{{data.count}}人
人已打赏
安全运维

Java定时框架Quartz实例详解与定时任务的Mongodb、Mysql持久化实现(一)Quartz组件

2021-12-11 11:36:11

安全运维

Ubuntu上NFS的安装配置

2021-12-19 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索