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 简单介绍
932AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。
1033
@@ -115,38 +138,38 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
115138 * @Description: 需要一次性拿一个许可的情况
116139 */
117140public 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 */
209232public 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 */
285308public 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 */
362385public 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