多线程面试题(四)---常用辅助类CountDownLatch/CyclicBarrier/Semaphore/ReadWriteLock

CountDownLatch
减法计数器: 实现调用几次线程后 再触发某一个任务

//减法计数器
CountDownLatch countDownLatch = new CountDownLatch(6);

for (int i = 1; i <= 6; i++) {
  new Thread(() -> {
    countDownLatch.countDown();// 数量-1
    System.out.println(Thread.currentThread().getName()+"  -1");
  }, String.valueOf(i)).start();
}

countDownLatch.await();//等待计数器归零,往下执行

System.out.println("计数器归零啦!!!");

原理

  • countDownLatch.countDown(); // 数量-1
  • countDownLatch.await(); //等待计数器归零,然后再向下执行
  • 每次有线程调用 countDown() 数量-1,假设计数器变为0,countDownLatch.await() 就会被唤醒,继续执行!

CyclicBarrier
sīklik berēər
加法计数器:集齐7颗龙珠召唤神龙

//减法计数器
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
  System.out.println("召唤神龙成功!");
});

for (int i = 1; i <= 7; i++) {
  final int temp=i;
  new Thread(() -> {
    System.out.println(Thread.currentThread().getName()+"收集第"+temp+"颗龙珠");
    try {
      cyclicBarrier.await();// 等待
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (BrokenBarrierException e) {
      e.printStackTrace();
    }
  }, String.valueOf(i)).start();
}

}

Semaphore

// 线程数量:停车位! 限流!、
// 如果已有3个线程执行(3个车位已满),则其他线程需要等待‘车位’释放后,才能执行!
Semaphore semaphore = new Semaphore(3);

for (int i = 1; i <=6 ; i++) {
  new Thread(()->{
    try {
      semaphore.acquire(); // 得到
      System.out.println(Thread.currentThread().getName()+"抢到车位");
      TimeUnit.SECONDS.sleep(2);
      System.out.println(Thread.currentThread().getName()+"离开车位");
    } catch (Exception e) {
      System.out.println(e);
    }finally {
      semaphore.release(); // 释放
    }

  },String.valueOf(i)).start();
}

原理
semaphore.acquire(); 获得,假设如果已经满了,等待,等待被释放为止!semaphore.release(); 释放,会将当前的信号量释放 + 1,然后唤醒等待的线程!
作用:
多个共享资源互斥的使用!并发限流,控制最大的线程数!

ReadWriteLock

public class ReadWriteLockDemo {

 public static void main (String[] args) throws Exception {

   /**
    *  * 独占锁(写锁) 一次只能被一个线程占有
    *  * 共享锁(读锁) 多个线程可以同时占有
    *  * ReadWriteLock
    *  * 读-读  可以共存!
    *  * 读-写  不能共存!
    *  * 写-写  不能共存!
    */
   MyCacheLock myCacheLock = new MyCacheLock();
   // 写入
   for (int i = 1; i <= 5 ; i++) {
     final int temp = i;
     new Thread(()->{
       myCacheLock.put(temp+"",temp+"");
     },String.valueOf(i)).start();
   }
   // 读取
   for (int i = 1; i <= 5 ; i++) {
     final int temp = i;
     new Thread(()->{
       myCacheLock.get(temp+"");
     },String.valueOf(i)).start();
   }
 }
}

class MyCacheLock {

 private Map<String, String> map = new HashMap<>();

 // 读写锁: 更加细粒度的控制
 private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
 // private Lock lock = new ReentrantLock();

 // 存,写入的时候,只希望同时只有一个线程写
 public void put (String key, String val) {
   readWriteLock.writeLock().lock();

   try {
     System.out.println(Thread.currentThread().getName() + "写入" + key);
     map.put(key, val);
     System.out.println(Thread.currentThread().getName() + "写入OK");

   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     readWriteLock.writeLock().unlock();
   }
 }

 // 取,读,所有人都可以读!
 public void get (String key) {
   readWriteLock.readLock().lock();

   try {
     System.out.println(Thread.currentThread().getName() + "读取" + key);
     Object o = map.get(key);
     System.out.println(Thread.currentThread().getName() + "读取OK");

   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     readWriteLock.readLock().unlock();
   }
 }
}

狂神JUC笔记:https://www.kuangstudy.com/bbs/1374937897278402561

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值