栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JUC并发编程的三个常用工具类使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JUC并发编程的三个常用工具类使用

常用的辅助类

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("关门了!");
    }
}

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();
    }

}

}

1.3 两者的比较
CountDownLatchCyclicBarrier
软件包java.util.concurrentjava.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();
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031467.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号