解决方案

CountDownLatch详解以及用法示例

seo靠我 2023-09-25 17:12:12

一、什么是CountDownLatch

CountDownLatch中count down是倒数的意思,latch则是门闩的含义。整体含义可以理解为倒数的门栓,似乎有一点“三二一,芝麻开门”的感觉。

CoSEO靠我untDownLatch的作用也是如此,在构造CountDownLatch(int count):的时候需要传入一个整数count,在这个整数“倒数”到0之前,主线程需要等待在门口,而这个“倒数”过程SEO靠我则是由各个执行线程驱动的,每个线程执行完一个任务“倒数”一次。

总结来说,CountDownLatch的作用就是等待其他的线程都执行完任务,必要时可以对各个任务的执行结果进行汇总,然后主线程才继续往下执SEO靠我行。

二、主要方法

CountDownLatch(int count):构造方法,创建一个新的 CountDownLatch 实例,用给定的计数初始化。参数 count 表示线程需要等待的任务数量。 SEO靠我 int numberOfTasks = 5; CountDownLatch latch = new CountDownLatch(numberOfTasksSEO靠我); void await():使当前线程等待,直到计数器值变为0,除非线程被 interrupted。如果计数器的值已经为0,则此方法立即返回。在实际应用中,通常在主线程中SEO靠我调用此方法,等待其他子线程完成任务。 latch.await(); boolean await(long timeout, TimeUnit unitSEO靠我):使当前线程等待,直到计数器值变为0,或者指定的等待时间已到,或者线程被 interrupted。如果计数器的值已经为0,则此方法立即返回。

参数 timeout 是指定的等待时间,

参数 unit 是SEO靠我 timeout 的单位(如秒、毫秒等)。

此方法返回一个布尔值,表示在等待时间内计数器是否变为0。 latch.await(5, TimeUnit.SECONDS);

这里需要注意的是,SEO靠我await()方法并没有规定只能有一个线程执行该方法,如果多个线程同时执行await()方法,那么这几个线程都将处于等待状态,并且以共享模式享有同一个锁。

void countDown():递减计数器的SEO靠我值。如果计数器的结果为0, 则释放所有等待的线程。在实际应用中,通常在线程完成任务后调用此方法。 latch.countDown();

这里需要注意的是,countDown()方法并没有SEO靠我规定一个线程只能调用一次,当同一个线程调用多次countDown()方法时,每次都会使计数器减一;

long getCount():获取当前计数的值。返回当前 CountDownLatch 实例内部的计SEO靠我数值。 long remainingCount = latch.getCount();

三、优缺点

优点: 简化了线程间的通信和同步。在某些并发场景中,需要等待其他线程完成任务后才能继续执SEO靠我行,使用 CountDownLatch 可以简化这种操作,而不需要复杂的锁和等待/通知机制。提高性能。由于 CountDownLatch 可以让线程在完成任务后立即递减计数值,而不需要等待其他线程完成SEO靠我任务,因此可以减少阻塞,提高程序运行性能。支持灵活的计数。可以通过创建不同的 CountDownLatch 实例,实现对多个线程任务计数。 缺点: 单次使用。CountDownLatSEO靠我ch 的计数值无法重置。一旦计数值到达零,它就不能再被使用了。在需要重复使用的场景中,可以选用 CyclicBarrier 或 Semaphore。没有返回值。CountDownLatch 无法获得执SEO靠我行任务的线程所返回的结果。如果需要收集线程执行结果,可以考虑使用 java.util.concurrent.Future 和 java.util.concurrent.ExecutorService。SEO靠我

四、使用场景

启动多个线程执行并行任务,主线程等待所有并行任务完成后继续执行。

例如:在测试中,准备数据阶段,需要同时查询多个子系统的数据和处理,等待处理结束后再进行下一步操作。控制线程的执行顺序。一个线SEO靠我程需要等待其他线程的结果或者完成任务后才能继续执行。

例如:一个文件解压缩程序,首先需要下载文件,下载完成后解压文件。实现一个计数器,允许一个或多个线程等待直到计数器为0。这对于在系统初始化时,需要等待SEO靠我资源加载或者初始化的场景十分有用。

例如:等待加载配置文件、启动连接池等操作完成后才开始处理其他任务。

四、示例代码

4.1 示例代码

下面的示例展示了一个简单的网站爬虫,它使用 CountDownLatchSEO靠我 在主线程中等待其他爬虫线程完成任务。

在这个例子中,我们要爬取一组网站的内容,在主线程中等待所有爬虫任务完成。

首先,我们创建一个 URLs 列表,包含多个网站 URL。

然后,我们使用 CountDowSEO靠我nLatch 实例 latch 来跟踪待完成的爬虫任务数量。

接着,我们遍历 URL 列表,为每个 URL 创建一个新的 Crawler 线程。Crawler 类实现了 Runnable 接口,用于读取SEO靠我指定 URL 的网页内容。在完成任务后,它调用 latch.countDown() 方法减少计数值。

最后,在主线程中,我们调用 latch.await() 方法等待所有爬虫线程完成任务。当所有任务完成SEO靠我时,打印一条消息表示爬虫任务已完成。

import java.io.BufferedReader; import java.io.InputStreamReader; iSEO靠我mport java.net.URL; import java.util.ArrayList; import java.util.List; imporSEO靠我t java.util.concurrent.CountDownLatch;public class WebCrawler {private static class Crawler implemenSEO靠我ts Runnable {private final String url;private final CountDownLatch latch;public Crawler(String url, SEO靠我CountDownLatch latch) {this.url = url;this.latch = latch;}@Overridepublic void run() {try {URL urlObSEO靠我ject = new URL(url);BufferedReader in = new BufferedReader(new InputStreamReader(urlObject.openStreaSEO靠我m()));String inputLine;StringBuilder content = new StringBuilder();while ((inputLine = in.readLine()SEO靠我) != null) {content.append(inputLine);content.append("\n");}in.close();System.out.println("爬取 " + urSEO靠我l + " 成功, 内容大小: " + content.length() + " 字符");} catch (Exception e) {System.err.println("爬取 " + url SEO靠我+ " 失败, 原因: " + e.getMessage());} finally {latch.countDown();}}}public static void main(String[] argSEO靠我s) throws InterruptedException {List<String> urls = new ArrayList<>();urls.add("https://github.com/"SEO靠我);urls.add("https://stackoverflow.com/");urls.add("https://www.zhihu.com/");urls.add("https://www.reSEO靠我ddit.com/");urls.add("https://www.linkedin.com/");CountDownLatch latch = new CountDownLatch(urls.sizSEO靠我e());System.out.println("开始爬虫任务...");for (String url : urls) {new Thread(new Crawler(url, latch)).stSEO靠我art();}latch.await();System.out.println("所有爬虫任务都已完成!");} }

4.2 运行结果

开始爬虫任务... 爬取 httpsSEO靠我://www.zhihu.com/ 成功, 内容大小: 37783 字符 爬取 https://github.com/ 成功, 内容大小: 227576 字符 爬取 hSEO靠我ttps://stackoverflow.com/ 成功, 内容大小: 171290 字符 爬取 https://www.linkedin.com/ 成功, 内容大小: 12603 字SEO靠我符 爬取 https://www.reddit.com/ 失败, 原因: Read timed out 所有爬虫任务都已完成!

五、稍复杂点的示例代码

5.1 代码示例讲解SEO靠我

这是一个稍复杂的 CountDownLatch 示例。

在这个例子中,我们将模拟一个简单的赛车游戏,

其中有一个倒计时开始。一旦倒计时结束,赛车就开始比赛,当所有赛车完成比赛时,主线程打印一条消息。 SEO靠我 import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit;publiSEO靠我c class CountDownLatchAdvancedDemo {public static void main(String[] args) throws InterruptedExceptiSEO靠我on {int numberOfRacers = 5;CountDownLatch startSignal = new CountDownLatch(1);CountDownLatch finishSSEO靠我ignal = new CountDownLatch(numberOfRacers);// 创建赛车线程for (int i = 0; i < numberOfRacers; i++) {new ThSEO靠我read(new Racer(startSignal, finishSignal)).start();}// 模拟倒计时System.out.println("倒计时开始...");for (int SEO靠我i = 3; i > 0; i--) {System.out.println("倒计时: " + i);TimeUnit.SECONDS.sleep(1);}System.out.println("比SEO靠我赛开始!");startSignal.countDown(); // 启动信号// 等待所有赛车完成比赛finishSignal.await();System.out.println("所有赛车都完成SEO靠我了比赛!");}static class Racer implements Runnable {private CountDownLatch startSignal;private CountDownSEO靠我Latch finishSignal;public Racer(CountDownLatch startSignal, CountDownLatch finishSignal) {this.startSEO靠我Signal = startSignal;this.finishSignal = finishSignal;}@Overridepublic void run() {try {// 等待开始信号staSEO靠我rtSignal.await();// 正在比赛System.out.println(Thread.currentThread().getName() + " 开始比赛...");Thread.sleSEO靠我ep((long) (Math.random() * 10000));System.out.println(Thread.currentThread().getName() + " 完成比赛!");}SEO靠我 catch (InterruptedException e) {e.printStackTrace();} finally {// 完成比赛后,递减完成信号计数finishSignal.countDSEO靠我own();}}} }

在这个例子中,我们创建了两个 CountDownLatch,

一个用于开始信号 (startSignal),另一个用于完成信号 (finishSignal)。创建赛SEO靠我车线程时,它们都需要等待开始信号。

当倒计时结束时,调用 startSignal.countDown(),开始信号变为0,并表示比赛开始。

每个线程在模拟赛车完成比赛后,调用 finishSignal.cSEO靠我ountDown() 减少完成信号计数。

主线程使用 finishSignal.await() 等待所有赛车线程都完成比赛。当计数值变为 0 时,主线程将打印一条消息表示所有赛车都完成了比赛。

5.2 运SEO靠我行结果

倒计时开始... 倒计时: 3 倒计时: 2 倒计时: 1 比赛开始! Thread-4 开始比赛... SEO靠我 Thread-2 开始比赛... Thread-0 开始比赛... Thread-1 开始比赛... Thread-3 开始比赛... SEO靠我 Thread-4 完成比赛! Thread-1 完成比赛! Thread-0 完成比赛! Thread-2 完成比赛! ThreSEO靠我ad-3 完成比赛! 所有赛车都完成了比赛!
“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2