常用的辅助类


文章目录

  • 常用的辅助类
  • 1. 同步工具类
  • 1.1 CountDownLatch
  • 概念
  • 方法
  • 案例
  • 1.2 CyclicBarrier
  • 概述
  • 构造器
  • 方法
  • 案例
  • 1.3 两者的比较
  • 2 Semaphore
  • 2.1 概念
  • 2.2 常用方法
  • 2.3 案例



JUC并发包下有四个并发工具类,闭锁CountDownlatch、栅栏CyclicBarrier、信号量Semaphore、交换器Exchanger。 本篇文章我们对前三个辅助类进行讲解。

1. 同步工具类

1.1 CountDownLatch
概念
  • CountDownLatch允许一个或者多个线程去等待其他线程完成操作。
  • CountDownLatch接收一个int型参数,表示要等待的工作线程的个数
方法
  • await():使当前线程进入同步队列进行等待,直到 latch 的值被减到0或者当前线程被中断,当前线程就会被唤醒。
  • await(long timeout, TimeUnit unit):带超时时间的await()。
  • countDown():使 latch 的值减1,如果减到了0,则会唤醒所有等待在这个 latch 上的线程。
  • getCount():获得latch的数值。
案例
//模拟放学锁门,只有六个同学全部走了,老师才可以锁门
public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        //总数为6
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "离开了教室");
                countDownLatch.countDown();//计数器-1
            },String.valueOf(i)).start();
        }
        //等待计数器归0再向下执行
        countDownLatch.await();
        System.out.println("关门了!");
    }
}

Java springutils常用工具类 juc java 工具类_构造器

1.2 CyclicBarrier
概述
  • CyclicBarrier:循环屏障,可以给离散的任务添加逻辑层次。
  • 各个线程会互相等待,直到所有线程都完成了,再一起突破屏障。如上课时,只有所有学生都到了,老师才会上课。
构造器
  • CyclicBarrier有两个构造器
  • CyclicBarrier(int parties) :创建一个CyclicBarrier对象,并指定其parties
  • CyclicBarrier(int parties, Runnable barrierAction) :指定parties,并且执行其callBack(在所有线程都到达时执行此barrierAction)
  • parties:当前CyclicBarrier管理的线程的个数
方法
  • await():等待所有 parties 已经在这个障碍上调用了await。如果当前线程不是最后一个线程,那么它被禁用以进行线程调度,并且处于休眠状态,直到发生下列事情之一:
  • 最后一个线程到达
  • 其他一些线程中断当前线程
  • 其他一些线程中断了其他等待线程中的一个
  • 其他一些线程在等待屏障时超时
  • 其他一些线程在这个屏障上调用 reset()
  • await(long timeout, TimeUnit unit):等待所有 parties已经在此屏障上调用 await ,或指定的等待时间过去。
  • getNumberWaiting():返回目前正在等待障碍的各方的数量。
  • getParties():返回突破障碍所需的数量
  • isBroken():查询这个障碍是否处于破碎状态。
  • reset():将屏障重置为初始状态。
案例
//模拟考试交卷,只有等到全部人交卷了,才可以走
 public class CyclicBarrierTest {
 public static void main(String[] args) {
 CyclicBarrier cyclicBarrier = new CyclicBarrier(6,()->{
 System.out.println(“考试结束,大家可以走了”);
 });
for (int i = 1; i <= 6; i++) {
        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();
            }
        },"学生" + i).start();
    }

}


Java springutils常用工具类 juc java 工具类_构造器_02

1.3 两者的比较

CountDownLatch

CyclicBarrier

软件包

java.util.concurrent

java.util.concurrent

适用情景

主线程等待多个工作线程结束

多个线程之间互相等待,直到所有线程达到一个障碍点(Barrier point)

等待结束

各线程之间不再互相影响,可以继续做自己的事情。不再执行下一个目标工作

在屏障点达到后,允许所有线程继续执行,达到下一个目标。可以重复使用CyclicBarrier

异常

如果其中一个线程由于中断,错误,或超时导致永久离开屏障点,其他线程也将抛出异常。

其他

如果BarrierAction不依赖于任何Party中的所有线程,那么在任何party中的一个线程被释放的时候,可以直接运行这个Action。

2 Semaphore

2.1 概念
  • Semaphore通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。
  • 作用:多个共享资源互斥的使用,并发限流,控制最大的线程数
2.2 常用方法
  • acquire():获取一个令牌,在获取到令牌、或者被其他线程调用中断之前线程一直处于阻塞状态。
  • acquire(int permits):获取一个令牌,在获取到令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状
  • acquireUninterruptibly():获取一个令牌,在获取到令牌之前线程一直处于阻塞状态(忽略中断)。
  • tryAcquire():尝试获得令牌,返回获取令牌成功或失败,不阻塞线程。
  • tryAcquire(long timeout, TimeUnit unit):尝试获得令牌,在超时时间内循环尝试获取,直到尝试获取成功或超时返回,不阻塞线程。
  • release():释放一个令牌,唤醒一个获取令牌不成功的阻塞线程。
  • hasQueuedThreads():等待队列里是否还存在等待线程。
  • getQueueLength():获取等待队列里阻塞的线程数。
  • drainPermits():清空令牌把可用令牌数置为0,返回清空令牌的数量。
  • availablePermits():返回可用的令牌数量。
2.3 案例
//模拟抢车位,只有三个车位,六辆车
public class SemaphoreTest {
    public static void main(String[] args) {
        //线程数量-三个车位
        Semaphore semaphore = new Semaphore(3);

        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();//acquire()得到,即抢到车位
                    System.out.println(Thread.currentThread().getName() + "抢到车位");
                    TimeUnit.SECONDS.sleep(2);//模拟停车时间为2s
                    System.out.println(Thread.currentThread().getName() + "离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();//release()释放,即离开车位
                }
            }).start();
        }
    }
}

Java springutils常用工具类 juc java 工具类_jvm_03