CountDownLatch、CyclicBarrier、Semaphore
{
"title":"AQS相关",
"date":2020-05-21T09:16:43+08:00,
"draft":true,
"tags":["CountDownLatch、CyclicBarrier、Semaphore"],
"comments":true,
"share":true
}
AQS 简单介绍
AQS 原理
CountDownLatch相关
CountDownLatch:让一些线程阻塞直到另外一些完成后才被唤醒。代码演示。
CountDownLatch主要有两个方法,当一个或多个线程调用await()方法时,调用线程会被阻塞。 其他线程调用countDown()方法计数器减1(调用countDown方法时线程不会阻塞),当计数器的值变为0, 因调用await方法被阻塞的线程会被唤醒,继续执行。 package com.xpf.Interview.juc.other; import java.util.concurrent.CountDownLatch; /** * @Author: Xia * @Date: 2020/5/21 9:30 * @Email:x2358114512@163.com 代码实现:等for里的线程完成结束后,main线程才能执行。 */ public class T { public static void main(String[] args) { notcountDownLatch(); countDownLatch(); } private static void countDownLatch() { CountDownLatch countDownLatch = new CountDownLatch(5); for (int i = 0; i < 5; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName()+"线程完成任务,回家"); countDownLatch.countDown(); },String.valueOf(i)).start(); } try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"线程完成任务,回家"); } private static void notcountDownLatch() { for(int i = 0;i<5;i++){ new Thread(() -> { System.out.println(Thread.currentThread().getName()+"线程完成任务,回家"); },String.valueOf(i)).start(); } System.out.println(Thread.currentThread().getName()+"线程完成任务,回家"); } } notcountDownLatch()函数的结果: 0线程完成任务,回家 3线程完成任务,回家 1线程完成任务,回家 main线程完成任务,回家 2线程完成任务,回家 4线程完成任务,回家 countDownLatch()函数的结果: 0线程完成任务,回家 1线程完成任务,回家 2线程完成任务,回家 4线程完成任务,回家 3线程完成任务,回家 main线程完成任务,回家
- CyclicBarrier相关
CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。线程进入屏障通过CyclicBarrier的await()方法。代码演示。
1. 线程进入屏障通过CyclicBarrier的await()方法。
2. 构造方法:public CyclicBarrier(int parties, Runnable barrierAction)
Runnable barrierAction指的是被阻塞的哪个线程
package com.xpf.Interview.juc.other; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /** * @Author: Xia * @Date: 2020/5/21 9:30 * @Email:x2358114512@163.com */ public class T { public static void main(String[] args) { cyclicBarrier(); } private static void cyclicBarrier() { CyclicBarrier cyclicBarrier = new CyclicBarrier(5,() -> { System.out.println(Thread.currentThread().getName()+"线程:前5个线程完成后,最后才会完成此线程"); }); for (int i = 0; i < 5; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName()+"线程:完成任务"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } } cyclicBarrier()函数执行结果: 0线程:完成任务 2线程:完成任务 3线程:完成任务 1线程:完成任务 4线程:完成任务 4线程:前5个线程完成后,最后才会完成此线程
- Semaphore相关
引出问题:之前的案列都是多线程访问同一份共享资源;对于多线程访问多份共享资源那怎么处理?
这里就可以引出Semaphore。 Semaphore(信号量)的作用:用于多线程调用多个共享资源的互斥使用,另外也可以用于并发线程数的控制。 package com.xpf.Interview.juc.other; import java.sql.Time; import java.util.concurrent.*; /** * @Author: Xia * @Date: 2020/5/21 9:30 * @Email:x2358114512@163.com 模拟5个车(5个线程)抢3个车位(3个资源) */ public class T { public static void main(String[] args) { semaphore(); } private static void semaphore() { Semaphore semaphore = new Semaphore(3); //模拟3个停车位(资源) for (int i = 0; i < 5; i++) { //模拟5部汽车(线程) new Thread(() -> { try{ semaphore.acquire(); //当前线程抢到资源 System.out.println(Thread.currentThread().getName()+"线程:抢到停车位"); TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+"线程:2秒后离开停车位"); }catch (Exception e){ e.printStackTrace(); }finally { semaphore.release(); //当前线程释放资源 } },String.valueOf(i)).start(); } } } semaphore()函数执行结果: 0线程:抢到停车位 1线程:抢到停车位 2线程:抢到停车位 0线程:2秒后离开停车位 2线程:2秒后离开停车位 3线程:抢到停车位 4线程:抢到停车位 1线程:2秒后离开停车位 3线程:2秒后离开停车位 4线程:2秒后离开停车位