Semaphore、CountDownLatch、CyclicBarrier的区别

ops/2024/9/24 19:15:16/

Semaphore、CountDownLatch和CyclicBarrier在Java中都是用于控制多线程执行的工具类,但它们各自有不同的使用场景和特性。

Semaphore(信号量)主要用于控制同时访问特定资源的线程数量。它允许一定数量的线程同时访问某个资源或资源池,通过获取和释放许可来协调各个线程的执行。Semaphore常用于实现如停车场提示牌功能等场景,确保资源得到合理的使用。

CountDownLatch是一个倒计时锁存器,它允许一个或多个线程等待其他线程完成操作。构造函数接收一个整数参数,表示计数的初始值。每当一个线程完成其任务后,计数减1,直到计数达到0,此时等待的线程会被唤醒并继续执行。CountDownLatch通常用于确保一组线程中的某些操作在所有线程都准备好之后再进行。

CyclicBarrier(循环屏障)则用于让一组线程互相等待,直到所有线程都到达某个公共屏障点。与CountDownLatch不同的是,CyclicBarrier的屏障可以在最后一次使用之后重置,因此它可以被循环使用。当所有线程都到达屏障点时,可以选择执行一个特定的操作,然后再继续执行。CyclicBarrier常用于需要所有线程都完成某个阶段的任务后才能进行下一阶段任务的场景。

总结来说,Semaphore、CountDownLatch和CyclicBarrier在控制多线程执行方面各有侧重。Semaphore关注资源的访问控制,CountDownLatch关注一组线程中某些操作的先后顺序,而CyclicBarrier则关注一组线程之间的相互等待和同步。根据具体需求,可以选择合适的工具类来实现多线程的协调和控制。

当然,下面我将用Java代码来展示SemaphoreCountDownLatchCyclicBarrier之间的区别。

首先是Semaphore的示例,它用于限制同时访问某个资源的线程数:

java">import java.util.concurrent.Semaphore;  public class SemaphoreExample {  private static final int MAX_PERMITS = 3; // 允许同时访问的最大线程数  private static Semaphore semaphore = new Semaphore(MAX_PERMITS);  public static void main(String[] args) {  for (int i = 0; i < 5; i++) {  new Thread(() -> {  try {  semaphore.acquire(); // 获取许可  System.out.println(Thread.currentThread().getName() + " 进入资源区");  // 模拟线程使用资源  Thread.sleep((long) (Math.random() * 1000));  } catch (InterruptedException e) {  e.printStackTrace();  } finally {  semaphore.release(); // 释放许可  System.out.println(Thread.currentThread().getName() + " 离开资源区");  }  }).start();  }  }  
}

执行结果:

接下来是CountDownLatch的示例,它用于等待一组线程完成某项操作:

java">import java.util.concurrent.CountDownLatch;  public class CountDownLatchExample {  private static final int THREAD_COUNT = 5;  private static CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);  public static void main(String[] args) throws InterruptedException {  for (int i = 0; i < THREAD_COUNT; i++) {  new Thread(() -> {  System.out.println(Thread.currentThread().getName() + " 正在执行任务");  // 模拟任务执行  try {  Thread.sleep((long) (Math.random() * 1000));  } catch (InterruptedException e) {  e.printStackTrace();  }  countDownLatch.countDown(); // 任务完成,计数器减一  }).start();  }  countDownLatch.await(); // 等待所有线程完成任务  System.out.println("所有线程任务完成");  }  
}

执行结果:

最后是CyclicBarrier的示例,它用于一组线程互相等待,直到所有线程都到达某个屏障点:

java">import java.util.concurrent.BrokenBarrierException;  
import java.util.concurrent.CyclicBarrier;  public class CyclicBarrierExample {  private static final int THREAD_COUNT = 5;  private static CyclicBarrier cyclicBarrier = new CyclicBarrier(THREAD_COUNT, () -> {  System.out.println("所有线程都到达了屏障点,可以执行额外的任务");  });  public static void main(String[] args) {  for (int i = 0; i < THREAD_COUNT; i++) {  new Thread(() -> {  System.out.println(Thread.currentThread().getName() + " 准备到达屏障点");  try {  cyclicBarrier.await(); // 等待所有线程到达屏障点  } catch (InterruptedException | BrokenBarrierException e) {  e.printStackTrace();  }  System.out.println(Thread.currentThread().getName() + " 已经通过屏障点");  }).start();  }  }  
}

执行结果:

在这三个示例中,你可以看到它们各自的使用场景和特性:

  • Semaphore用于限制同时访问资源的线程数,通过获取和释放许可来协调线程的执行。
  • CountDownLatch用于等待一组线程完成某项操作,通过计数器来确保所有线程都完成后再继续执行后续任务。
  • CyclicBarrier用于一组线程相互等待,直到所有线程都到达某个屏障点,之后可以一起执行某个任务或者进入下一阶段。

这些工具类在并发编程中非常有用,它们提供了不同的同步机制来协调和控制多线程的执行顺序。选择哪个工具类取决于具体的业务需求和应用场景。


http://www.ppmy.cn/ops/15376.html

相关文章

Mysql主从复制

概述 主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从库服务器中&#xff0c;然后在从库上对这些日志重新执行&#xff08;也叫重做&#xff09;&#xff0c;从而使得从库和主库的数据保持同步。 MySQL支持一台主库同时向多台从库进行复制&#xff0c;从库同时也可…

从 Android 恢复已删除文件的 3 种简单方法

如何从 Android 恢复已删除的文件&#xff1f;毫不犹豫&#xff0c;有些人可能会认为从 Google 备份恢复 Android 文件太容易了。但是&#xff0c;如果删除的文件未同步到您的帐户或未备份怎么办&#xff1f;您错误的恢复可能会永久删除您想要的数据。因此&#xff0c;我们发布…

从预训练损失的角度,理解语言模型的涌现能力

原文&#xff1a;Understanding Emergent Abilities of Language Models from the Loss Perspective 摘要 本文从预训练损失的角度重新审视语言模型的涌现能力&#xff0c;挑战了以往以模型大小或训练计算量为标准的观念。通过实验&#xff0c;作者发现预训练损失是预测下游任…

pycharm爬虫模块(scrapy)基础使用

今天学了个爬虫。在此记录 目录 一.通过scrapy在命令行创建爬虫项目 二.判断数据为静态还是动态 三.pycharm中的设置 三:爬虫主体 四.pipelines配置&#xff08;保存数据的&#xff09; 五.最终结果 一.通过scrapy在命令行创建爬虫项目 1.首先需要在cmd中进入到python文…

设计模式-开闭原则和迪米特法则

开闭原则 基本介绍 开闭原则(Open Closed Principle) 是编程中最基础、最重要的设计原则一个软件实体如类&#xff0c;模块和函数应该对扩展开放(对提供方)&#xff0c;对修改关闭(对使用方)。用抽象构建框架&#xff0c;用实现扩展细节。当软件需要变化时&#xff0c;尽量通…

软件设计师-基础知识科目-计算题汇总1

1. 位运算&#xff1a; 略 2. 进制转换&#xff1a; 3. 计算内存存储容量&#xff1a; 前置概念&#xff1a;** 内存地址是16进制。 16进制后面的加上的字母H&#xff0c;表示数字为16进制。内存地址编址的单位是Byte&#xff0c;1K 1024B&#xff0c;1024用16进制表示为400H …

LabVIEW卡尔曼滤波技术

LabVIEW卡尔曼滤波技术 在现代航空导航中&#xff0c;高精度和快速响应的方位解算对于航空安全至关重要。通过LabVIEW平台实现一种卡尔曼滤波方位解算修正技术&#xff0c;以改善传统导航设备在方位解算中的噪声干扰问题&#xff0c;从而提高其解算精度和效率。通过LabVIEW的强…

windows SDK编程 --- 消息(3)

前置知识 一、消息的分类 1. 鼠标消息 处理与鼠标交互相关的事件&#xff0c;比如移动、点击和滚动等。例如&#xff1a; WM_MOUSEMOVE: 当鼠标在窗口客户区内移动时发送。WM_LBUTTONDOWN: 当用户按下鼠标左键时发送。WM_LBUTTONUP: 当用户释放鼠标左键时发送。WM_RBUTTOND…