Skip to content

Commit 5d8a473

Browse files
authored
Add:目录
1 parent d89fc9f commit 5d8a473

File tree

1 file changed

+161
-138
lines changed

1 file changed

+161
-138
lines changed

Java相关/Multithread/AQS.md

Lines changed: 161 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
11

2-
> 常见问题:AQS 原理?;CountDownLatch和CyclicBarrier了解吗,两者的区别是什么?用过Semaphore吗?
2+
3+
> 常见问题:AQS原理?;CountDownLatch和CyclicBarrier了解吗,两者的区别是什么?用过Semaphore吗?
34
45
**本节思维导图:**
56

67
![并发编程面试必备:AQS 原理以及 AQS 同步组件总结](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-31/61115865.jpg)
78

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+
831
### 1 AQS 简单介绍
932
AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。
1033

@@ -115,38 +138,38 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
115138
* @Description: 需要一次性拿一个许可的情况
116139
*/
117140
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+
}
150173
}
151174
```
152175

@@ -155,9 +178,9 @@ public class SemaphoreExample1 {
155178
当然一次也可以一次拿取和释放多个许可,不过一般没有必要这样做:
156179

157180
```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
161184
```
162185

163186
除了 `acquire`方法之外,另一个比较常用的与之对应的方法是`tryAcquire`方法,该方法如果获取不到许可就立即返回false。
@@ -207,37 +230,37 @@ CountDownLatch是一个同步工具类,它允许一个或多个线程一直等
207230
* @Description: CountDownLatch 使用方法示例
208231
*/
209232
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+
}
241264
}
242265

243266
```
@@ -283,42 +306,42 @@ CyclicBarrier 可以用于多线程计算数据,最后合并计算结果的应
283306
* @Description: 测试 CyclicBarrier 类中带参数的 await() 方法
284307
*/
285308
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+
}
322345

323346
}
324347
```
@@ -360,40 +383,40 @@ threadnum:6is finish
360383
* @Description: 新建 CyclicBarrier 的时候指定一个 Runnable
361384
*/
362385
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+
}
397420

398421
}
399422
```
@@ -449,4 +472,4 @@ ReentrantLock 和 synchronized 的区别在上面已经讲过了这里就不多
449472

450473
由于篇幅问题,关于 ReentrantLock 和 ReentrantReadWriteLock 详细内容可以查看我的这篇原创文章。
451474

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

Comments
 (0)