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靠我程需要等待其他线程的结果或者完成任务后才能继续执行。
例如:一个文件解压缩程序,首先需要下载文件,下载完成后解压文件。实现一个计数器,允许一个或多个线程等待直到计数器为0。这对于在系统初始化时,需要等待SEO靠我资源加载或者初始化的场景十分有用。
例如:等待加载配置文件、启动连接池等操作完成后才开始处理其他任务。下面的示例展示了一个简单的网站爬虫,它使用 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("所有爬虫任务都已完成!");} }这是一个稍复杂的 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 时,主线程将打印一条消息表示所有赛车都完成了比赛。
网站备案号:浙ICP备17034767号-2