并发编程——并行(CountDownLatch、CyclicBarrier、Semaphore)

问题场景:

解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景,可以用到CountDownLatch,CyclicBarrier。

多个线程同时操作同个资源,并且可以排队、限流,可以用到Semaphore。

一、计数器(CountDownLatch)

介绍:CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计      数器递减到0时会唤醒阻塞队列所有线程。

常用方法说明:

CountDownLatch(int count); //构造方法,创建一个值为count 的计数器。

await();//阻塞当前线程,将当前线程加入阻塞队列。

​await(long timeout, TimeUnit unit);//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行.

countDown();//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。

代码示例:https://blog.csdn.net/qq_37184877/article/details/107108743

二、循环屏障(CyclicBarrier)

介绍:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

常用方法说明:

public CyclicBarrier(int parties);  //构造  给定数量的参与者(线程)处于等待状态时启动

public CyclicBarrier(int parties, Runnable barrierAction);//构造  最后一个进入 barrier 的线程执行 

int await() 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。

int await(long timeout, TimeUnit unit) 在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。

int getNumberWaiting() 返回当前在屏障处等待的参与者数目。

int getParties() 返回要求启动此 barrier 的参与者数目。

boolean isBroken() 查询此屏障是否处于损坏状态。

void reset() 将屏障重置为其初始状态。

代码示例:

package com.hxl.utils.thread.token.cyclicDome;

import java.util.concurrent.CyclicBarrier;

/**
 * 循环屏障
 */
public class CyclicWorker implements Runnable {


    private CyclicBarrier cyclicBarrier;

    private String name;

    public CyclicWorker(CyclicBarrier cyclicBarrier, String name){
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            Thread.sleep((long) (Math.random() * 10000));
            System.out.println(name + " 到达栅栏 ");
            this.cyclicBarrier.await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public static void main(String[] args) {
        final int count = 4;
        final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() {

            @Override
            public void run() {
                System.out.println("任务 1-4 都做完了,执行下一步,主逻辑5");
            }
        });

        for (int i = 1; i <= count; i++){
            new Thread(new CyclicWorker(barrier,"任务"+i)).start();
        }
    }
}

三、信号量(Semaphore)

介绍:Semaphore 是一个计数信号量,必须由获取它的线程释放。常用于限制可以访问某些资源的线程数量,例如通过 Semaphore 限流。只有三个操作:初始化、增加、减小。Semaphore与锁类似,但是与锁不同的是,Synchronized是独占式的,同一时刻只有一个线程能够操作资源,而Semaphore允许指定的多个线程同时操作同个资源。它通过获取许可,释放许可来控制多个线程操作资源。

常用方法:

acquire()  获取一个令牌,在获取到令牌、或者被其他线程调用中断之前线程一直处于阻塞状态。

​acquire(int permits)  获取一个令牌,在获取到令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状态。    

acquireUninterruptibly() 获取一个令牌,在获取到令牌之前线程一直处于阻塞状态(忽略中断)。

tryAcquire() 尝试获得令牌,返回获取令牌成功或失败,不阻塞线程。

​tryAcquire(long timeout, TimeUnit unit) 尝试获得令牌,在超时时间内循环尝试获取,直到尝试获取成功或超时返回,不阻塞线程。

​release() 释放一个令牌,唤醒一个获取令牌不成功的阻塞线程。

​hasQueuedThreads() 等待队列里是否还存在等待线程。

getQueueLength()  获取等待队列里阻塞的线程数。

​drainPermits()  清空令牌把可用令牌数置为0,返回清空令牌的数量。​

availablePermits()  返回可用的令牌数量

代码示例

网吧有5台电脑,但是现在有8个人进入网吧,同一时间只能有5个人上机

 public static void main(String[] args) {
        int N = 8; //学生数
        Semaphore semaphore = new Semaphore(5); //电脑数目
        for(int i=0;i<N;i++)
            new Worker(i,semaphore).start();
    }

    static class Worker extends Thread{
        private int num;
        private Semaphore semaphore;

        public Worker(int num,Semaphore semaphore){
            this.semaphore = semaphore;
            this.num = num;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire();
                System.out.println("同学"+this.num+"占用一台电脑...");
                Thread.sleep(2000);
                System.out.println("--同学"+this.num+"离开电脑");
                semaphore.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

四、CountDownLatch和CyclicBarrier区别

  • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
  • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。(CountDownLatch 等待到齐结束是主线程,CyclicBarrier  等待到齐结束是子线程)

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值