1
1
2
- > 常见问题:AQS 原理?;CountDownLatch和CyclicBarrier了解吗,两者的区别是什么?用过Semaphore吗?
2
+
3
+ > 常见问题:AQS原理?;CountDownLatch和CyclicBarrier了解吗,两者的区别是什么?用过Semaphore吗?
3
4
4
5
** 本节思维导图:**
5
6
6
7
![ 并发编程面试必备:AQS 原理以及 AQS 同步组件总结] ( http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-31/61115865.jpg )
7
8
9
+ <!-- MarkdownTOC -->
10
+
11
+ - [ 1 AQS 简单介绍] ( #1-aqs-简单介绍 )
12
+ - [ 2 AQS 原理] ( #2-aqs-原理 )
13
+ - [ 2.1 AQS 原理概览] ( #21-aqs-原理概览 )
14
+ - [ 2.2 AQS 对资源的共享方式] ( #22-aqs-对资源的共享方式 )
15
+ - [ 2.3 AQS底层使用了模板方法模式] ( #23-aqs底层使用了模板方法模式 )
16
+ - [ 3 Semaphore\( 信号量\) -允许多个线程同时访问] ( #3-semaphore信号量-允许多个线程同时访问 )
17
+ - [ 4 CountDownLatch (倒计时器)] ( #4-countdownlatch-(倒计时器) )
18
+ - [ 4.1 CountDownLatch 的三种典型用法] ( #41-countdownlatch-的三种典型用法 )
19
+ - [ 4.2 CountDownLatch 的使用示例] ( #42-countdownlatch-的使用示例 )
20
+ - [ 4.3 CountDownLatch 的不足] ( #43-countdownlatch-的不足 )
21
+ - [ 4.4 CountDownLatch相常见面试题:] ( #44-countdownlatch相常见面试题: )
22
+ - [ 5 CyclicBarrier\( 循环栅栏\) ] ( #5-cyclicbarrier循环栅栏 )
23
+ - [ 5.1 CyclicBarrier 的应用场景] ( #51-cyclicbarrier-的应用场景 )
24
+ - [ 5.2 CyclicBarrier 的使用示例] ( #52-cyclicbarrier-的使用示例 )
25
+ - [ 5.3 CyclicBarrier和CountDownLatch的区别] ( #53-cyclicbarrier和countdownlatch的区别 )
26
+ - [ 6 ReentrantLock 和 ReentrantReadWriteLock] ( #6-reentrantlock-和-reentrantreadwritelock )
27
+
28
+ <!-- /MarkdownTOC -->
29
+
30
+
8
31
### 1 AQS 简单介绍
9
32
AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。
10
33
@@ -115,38 +138,38 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
115
138
* @Description: 需要一次性拿一个许可的情况
116
139
*/
117
140
public class SemaphoreExample1 {
118
- // 请求的数量
119
- private static final int threadCount = 550 ;
120
-
121
- public static void main (String [] args ) throws InterruptedException {
122
- // 创建一个具有固定线程数量的线程池对象(如果这里线程池的线程数量给太少的话你会发现执行的很慢)
123
- ExecutorService threadPool = Executors . newFixedThreadPool(300 );
124
- // 一次只能允许执行的线程数量。
125
- final Semaphore semaphore = new Semaphore (20 );
126
-
127
- for (int i = 0 ; i < threadCount; i++ ) {
128
- final int threadnum = i;
129
- threadPool. execute(() - > {// Lambda 表达式的运用
130
- try {
131
- semaphore. acquire();// 获取一个许可,所以可运行线程数量为20/1=20
132
- test(threadnum);
133
- semaphore. release();// 释放一个许可
134
- } catch (InterruptedException e) {
135
- // TODO Auto-generated catch block
136
- e. printStackTrace();
137
- }
138
-
139
- });
140
- }
141
- threadPool. shutdown();
142
- System . out. println(" finish" );
143
- }
144
-
145
- public static void test (int threadnum ) throws InterruptedException {
146
- Thread . sleep(1000 );// 模拟请求的耗时操作
147
- System . out. println(" threadnum:" + threadnum);
148
- Thread . sleep(1000 );// 模拟请求的耗时操作
149
- }
141
+ // 请求的数量
142
+ private static final int threadCount = 550 ;
143
+
144
+ public static void main (String [] args ) throws InterruptedException {
145
+ // 创建一个具有固定线程数量的线程池对象(如果这里线程池的线程数量给太少的话你会发现执行的很慢)
146
+ ExecutorService threadPool = Executors . newFixedThreadPool(300 );
147
+ // 一次只能允许执行的线程数量。
148
+ final Semaphore semaphore = new Semaphore (20 );
149
+
150
+ for (int i = 0 ; i < threadCount; i++ ) {
151
+ final int threadnum = i;
152
+ threadPool. execute(() - > {// Lambda 表达式的运用
153
+ try {
154
+ semaphore. acquire();// 获取一个许可,所以可运行线程数量为20/1=20
155
+ test(threadnum);
156
+ semaphore. release();// 释放一个许可
157
+ } catch (InterruptedException e) {
158
+ // TODO Auto-generated catch block
159
+ e. printStackTrace();
160
+ }
161
+
162
+ });
163
+ }
164
+ threadPool. shutdown();
165
+ System . out. println(" finish" );
166
+ }
167
+
168
+ public static void test (int threadnum ) throws InterruptedException {
169
+ Thread . sleep(1000 );// 模拟请求的耗时操作
170
+ System . out. println(" threadnum:" + threadnum);
171
+ Thread . sleep(1000 );// 模拟请求的耗时操作
172
+ }
150
173
}
151
174
```
152
175
@@ -155,9 +178,9 @@ public class SemaphoreExample1 {
155
178
当然一次也可以一次拿取和释放多个许可,不过一般没有必要这样做:
156
179
157
180
``` java
158
- semaphore. acquire(5 );// 获取5个许可,所以可运行线程数量为20/5=4
159
- test(threadnum);
160
- semaphore. release(5 );// 获取5个许可,所以可运行线程数量为20/5=4
181
+ semaphore. acquire(5 );// 获取5个许可,所以可运行线程数量为20/5=4
182
+ test(threadnum);
183
+ semaphore. release(5 );// 获取5个许可,所以可运行线程数量为20/5=4
161
184
```
162
185
163
186
除了 ` acquire ` 方法之外,另一个比较常用的与之对应的方法是` tryAcquire ` 方法,该方法如果获取不到许可就立即返回false。
@@ -207,37 +230,37 @@ CountDownLatch是一个同步工具类,它允许一个或多个线程一直等
207
230
* @Description: CountDownLatch 使用方法示例
208
231
*/
209
232
public class CountDownLatchExample1 {
210
- // 请求的数量
211
- private static final int threadCount = 550 ;
212
-
213
- public static void main (String [] args ) throws InterruptedException {
214
- // 创建一个具有固定线程数量的线程池对象(如果这里线程池的线程数量给太少的话你会发现执行的很慢)
215
- ExecutorService threadPool = Executors . newFixedThreadPool(300 );
216
- final CountDownLatch countDownLatch = new CountDownLatch (threadCount);
217
- for (int i = 0 ; i < threadCount; i++ ) {
218
- final int threadnum = i;
219
- threadPool. execute(() - > {// Lambda 表达式的运用
220
- try {
221
- test(threadnum);
222
- } catch (InterruptedException e) {
223
- // TODO Auto-generated catch block
224
- e. printStackTrace();
225
- } finally {
226
- countDownLatch. countDown();// 表示一个请求已经被完成
227
- }
228
-
229
- });
230
- }
231
- countDownLatch. await();
232
- threadPool. shutdown();
233
- System . out. println(" finish" );
234
- }
235
-
236
- public static void test (int threadnum ) throws InterruptedException {
237
- Thread . sleep(1000 );// 模拟请求的耗时操作
238
- System . out. println(" threadnum:" + threadnum);
239
- Thread . sleep(1000 );// 模拟请求的耗时操作
240
- }
233
+ // 请求的数量
234
+ private static final int threadCount = 550 ;
235
+
236
+ public static void main (String [] args ) throws InterruptedException {
237
+ // 创建一个具有固定线程数量的线程池对象(如果这里线程池的线程数量给太少的话你会发现执行的很慢)
238
+ ExecutorService threadPool = Executors . newFixedThreadPool(300 );
239
+ final CountDownLatch countDownLatch = new CountDownLatch (threadCount);
240
+ for (int i = 0 ; i < threadCount; i++ ) {
241
+ final int threadnum = i;
242
+ threadPool. execute(() - > {// Lambda 表达式的运用
243
+ try {
244
+ test(threadnum);
245
+ } catch (InterruptedException e) {
246
+ // TODO Auto-generated catch block
247
+ e. printStackTrace();
248
+ } finally {
249
+ countDownLatch. countDown();// 表示一个请求已经被完成
250
+ }
251
+
252
+ });
253
+ }
254
+ countDownLatch. await();
255
+ threadPool. shutdown();
256
+ System . out. println(" finish" );
257
+ }
258
+
259
+ public static void test (int threadnum ) throws InterruptedException {
260
+ Thread . sleep(1000 );// 模拟请求的耗时操作
261
+ System . out. println(" threadnum:" + threadnum);
262
+ Thread . sleep(1000 );// 模拟请求的耗时操作
263
+ }
241
264
}
242
265
243
266
```
@@ -283,42 +306,42 @@ CyclicBarrier 可以用于多线程计算数据,最后合并计算结果的应
283
306
* @Description: 测试 CyclicBarrier 类中带参数的 await() 方法
284
307
*/
285
308
public class CyclicBarrierExample2 {
286
- // 请求的数量
287
- private static final int threadCount = 550 ;
288
- // 需要同步的线程数量
289
- private static final CyclicBarrier cyclicBarrier = new CyclicBarrier (5 );
290
-
291
- public static void main (String [] args ) throws InterruptedException {
292
- // 创建线程池
293
- ExecutorService threadPool = Executors . newFixedThreadPool(10 );
294
-
295
- for (int i = 0 ; i < threadCount; i++ ) {
296
- final int threadNum = i;
297
- Thread . sleep(1000 );
298
- threadPool. execute(() - > {
299
- try {
300
- test(threadNum);
301
- } catch (InterruptedException e) {
302
- // TODO Auto-generated catch block
303
- e. printStackTrace();
304
- } catch (BrokenBarrierException e) {
305
- // TODO Auto-generated catch block
306
- e. printStackTrace();
307
- }
308
- });
309
- }
310
- threadPool. shutdown();
311
- }
312
-
313
- public static void test (int threadnum ) throws InterruptedException , BrokenBarrierException {
314
- System . out. println(" threadnum:" + threadnum + " is ready" );
315
- try {
316
- cyclicBarrier. await(2000 , TimeUnit . MILLISECONDS );
317
- } catch (Exception e) {
318
- System . out. println(" -----CyclicBarrierException------" );
319
- }
320
- System . out. println(" threadnum:" + threadnum + " is finish" );
321
- }
309
+ // 请求的数量
310
+ private static final int threadCount = 550 ;
311
+ // 需要同步的线程数量
312
+ private static final CyclicBarrier cyclicBarrier = new CyclicBarrier (5 );
313
+
314
+ public static void main (String [] args ) throws InterruptedException {
315
+ // 创建线程池
316
+ ExecutorService threadPool = Executors . newFixedThreadPool(10 );
317
+
318
+ for (int i = 0 ; i < threadCount; i++ ) {
319
+ final int threadNum = i;
320
+ Thread . sleep(1000 );
321
+ threadPool. execute(() - > {
322
+ try {
323
+ test(threadNum);
324
+ } catch (InterruptedException e) {
325
+ // TODO Auto-generated catch block
326
+ e. printStackTrace();
327
+ } catch (BrokenBarrierException e) {
328
+ // TODO Auto-generated catch block
329
+ e. printStackTrace();
330
+ }
331
+ });
332
+ }
333
+ threadPool. shutdown();
334
+ }
335
+
336
+ public static void test (int threadnum ) throws InterruptedException , BrokenBarrierException {
337
+ System . out. println(" threadnum:" + threadnum + " is ready" );
338
+ try {
339
+ cyclicBarrier. await(2000 , TimeUnit . MILLISECONDS );
340
+ } catch (Exception e) {
341
+ System . out. println(" -----CyclicBarrierException------" );
342
+ }
343
+ System . out. println(" threadnum:" + threadnum + " is finish" );
344
+ }
322
345
323
346
}
324
347
```
@@ -360,40 +383,40 @@ threadnum:6is finish
360
383
* @Description: 新建 CyclicBarrier 的时候指定一个 Runnable
361
384
*/
362
385
public class CyclicBarrierExample3 {
363
- // 请求的数量
364
- private static final int threadCount = 550 ;
365
- // 需要同步的线程数量
366
- private static final CyclicBarrier cyclicBarrier = new CyclicBarrier (5 , () - > {
367
- System . out. println(" ------当线程数达到之后,优先执行------" );
368
- });
369
-
370
- public static void main (String [] args ) throws InterruptedException {
371
- // 创建线程池
372
- ExecutorService threadPool = Executors . newFixedThreadPool(10 );
373
-
374
- for (int i = 0 ; i < threadCount; i++ ) {
375
- final int threadNum = i;
376
- Thread . sleep(1000 );
377
- threadPool. execute(() - > {
378
- try {
379
- test(threadNum);
380
- } catch (InterruptedException e) {
381
- // TODO Auto-generated catch block
382
- e. printStackTrace();
383
- } catch (BrokenBarrierException e) {
384
- // TODO Auto-generated catch block
385
- e. printStackTrace();
386
- }
387
- });
388
- }
389
- threadPool. shutdown();
390
- }
391
-
392
- public static void test (int threadnum ) throws InterruptedException , BrokenBarrierException {
393
- System . out. println(" threadnum:" + threadnum + " is ready" );
394
- cyclicBarrier. await();
395
- System . out. println(" threadnum:" + threadnum + " is finish" );
396
- }
386
+ // 请求的数量
387
+ private static final int threadCount = 550 ;
388
+ // 需要同步的线程数量
389
+ private static final CyclicBarrier cyclicBarrier = new CyclicBarrier (5 , () - > {
390
+ System . out. println(" ------当线程数达到之后,优先执行------" );
391
+ });
392
+
393
+ public static void main (String [] args ) throws InterruptedException {
394
+ // 创建线程池
395
+ ExecutorService threadPool = Executors . newFixedThreadPool(10 );
396
+
397
+ for (int i = 0 ; i < threadCount; i++ ) {
398
+ final int threadNum = i;
399
+ Thread . sleep(1000 );
400
+ threadPool. execute(() - > {
401
+ try {
402
+ test(threadNum);
403
+ } catch (InterruptedException e) {
404
+ // TODO Auto-generated catch block
405
+ e. printStackTrace();
406
+ } catch (BrokenBarrierException e) {
407
+ // TODO Auto-generated catch block
408
+ e. printStackTrace();
409
+ }
410
+ });
411
+ }
412
+ threadPool. shutdown();
413
+ }
414
+
415
+ public static void test (int threadnum ) throws InterruptedException , BrokenBarrierException {
416
+ System . out. println(" threadnum:" + threadnum + " is ready" );
417
+ cyclicBarrier. await();
418
+ System . out. println(" threadnum:" + threadnum + " is finish" );
419
+ }
397
420
398
421
}
399
422
```
@@ -449,4 +472,4 @@ ReentrantLock 和 synchronized 的区别在上面已经讲过了这里就不多
449
472
450
473
由于篇幅问题,关于 ReentrantLock 和 ReentrantReadWriteLock 详细内容可以查看我的这篇原创文章。
451
474
452
- - [ ReentrantLock 和 ReentrantReadWriteLock] ( https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483745&idx=2&sn=6778ee954a19816310df54ef9a3c2f8a&chksm=fd985700caefde16b9970f5e093b0c140d3121fb3a8458b11871e5e9723c5fd1b5a961fd2228&token=1829606453&lang=zh_CN#rd )
475
+ - [ ReentrantLock 和 ReentrantReadWriteLock] ( https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483745&idx=2&sn=6778ee954a19816310df54ef9a3c2f8a&chksm=fd985700caefde16b9970f5e093b0c140d3121fb3a8458b11871e5e9723c5fd1b5a961fd2228&token=1829606453&lang=zh_CN#rd )
0 commit comments