Java实现限定时间CountDownLatch并行场景

  

让我们详细讲解“Java实现限定时间CountDownLatch并行场景”的完整攻略。

CountDownLatch概述

CountDownLatch是Java中一个非常实用的工具,它可以用于协调多个线程之间的同步操作。它可以让等待某个特定条件发生的线程一直等待下去,直到该条件被满足后,所有等待的线程才会同时被唤醒并继续执行。

CountDownLatch的核心思想就是一个计数器,该计数器被初始化为一个正整数,并且在某些操作发生之后被递减。一组等待中的线程可以被阻塞,直到计数器为零。如果你只是需要一个简单的同步工具,并不像Semaphore这样复杂和强大,那么CountDownLatch是个不错的选择。

CountDownLatch的使用

CountDownLatch的使用比较简单,主要包括以下步骤:

  1. 创建一个CountDownLatch对象,并指定计数器的初始值(即需要等待的操作数)。
  2. 在工作线程中执行需要等待的操作。
  3. 在等待线程中使用await()方法等待操作完成。
  4. 在工作线程中完成每个操作时,使用countDown()方法递减计数器的值。

Java实现限定时间CountDownLatch并行场景攻略及示例代码

Java实现限定时间CountDownLatch并行场景攻略的步骤如下:

  1. 创建一个 CountDownLatch 对象,计数器的初始值设为要等待的操作数 N,即需要等待 N 个线程的操作完成。
  2. 在每个工作线程中执行相应的任务,然后使用 countDown() 方法递减计数器的值。如果递减后的值为0,则所有操作已完成。
  3. 在等待线程中,调用 await(long timeout, TimeUnit unit) 方法等待操作完成或超时。超时时间可以由参数指定。

下面是示例代码,其中有两个工作线程并行执行,主线程等待它们完成或超时:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class CountDownLatchDemo {
    private static final int WORKER_NUM = 2;
    private static final int WAIT_TIME = 5000;

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(WORKER_NUM);

        // 创建两个工作线程
        new Thread(new Worker(latch, "Worker1")).start();
        new Thread(new Worker(latch, "Worker2")).start();

        // 在主线程中等待操作完成或超时
        if (latch.await(WAIT_TIME, TimeUnit.MILLISECONDS)) {
            System.out.println("All workers finished the job!");
        } else {
            System.out.println("Timeout! Some workers are not finished yet.");
        }
    }

    // 工作线程
    static class Worker implements Runnable {
        private final CountDownLatch latch;
        private final String name;

        public Worker(CountDownLatch latch, String name) {
            this.latch = latch;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                // 执行任务
                System.out.println(name + " is starting to work...");
                TimeUnit.SECONDS.sleep(3);
                System.out.println(name + " finished the job!");

                // 递减计数器
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述示例代码中,创建了一个 CountDownLatch 对象 latch,并指定初始值为 2(即需要等待两个工作线程完成操作)。然后创建两个工作线程 Worker1 和 Worker2,在每个工作线程中执行相应任务,最终使用 countDown() 方法递减计数器的值。在主线程中使用 await(long timeout, TimeUnit unit) 方法等待两个工作线程完成操作或超时。如果所有工作线程在指定的时间内完成操作,主线程输出 "All workers finished the job!"。如果有任何一个工作线程还没有完成操作,则主线程输出 "Timeout! Some workers are not finished yet."。

另外,这里再给一个更实际的例子,假如我们需要在10秒内获取多个网站的内容,而每个网站的内容获取可能会需要不同时间,此时我们可以使用CountDownLatch来实现并行获取,然后将结果进行合并。具体操作流程如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class CountDownLatchDemo {
    private static final int NUM_SITES = 5;
    private static final int WAIT_TIME = 10;
    private static final Random random = new Random();

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(NUM_SITES);
        List<String> contents = new ArrayList<>();

        // 并行获取各个网站的内容
        for (int i = 0; i < NUM_SITES; i++) {
            new Thread(new SiteContentFetcher(latch, contents)).start();
        }

        // 等待所有网站的内容获取完成或超时
        if (latch.await(WAIT_TIME, TimeUnit.SECONDS)) {
            System.out.println("All site contents fetched: " + contents);
        } else {
            System.out.println("Timeout!");
        }
    }

    // 获取单个网站的内容
    static class SiteContentFetcher implements Runnable {
        private final CountDownLatch latch;
        private final List<String> contents;

        public SiteContentFetcher(CountDownLatch latch, List<String> contents) {
            this.latch = latch;
            this.contents = contents;
        }

        @Override
        public void run() {
            try {
                // 模拟获取网站内容的时间
                long time = random.nextInt(10);
                System.out.println(Thread.currentThread().getName() + " fetching site content, time: " + time);
                TimeUnit.SECONDS.sleep(time);

                // 保存网站内容
                contents.add(Thread.currentThread().getName() + ": content");
                System.out.println(Thread.currentThread().getName() + " finished fetching site content");

                // 递减计数器
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述示例代码中,创建了一个 CountDownLatch 对象 latch,并指定初始值为 NUM_SITES(即需要等待 NUM_SITES 个网站的内容获取完成)。然后创建 NUM_SITES 个获取网站内容的工作线程,在每个工作线程中模拟获取网站内容的时间,实际获取网站内容并将其保存到列表中,最后使用 countDown() 方法递减计数器的值。在主线程中使用 await(long timeout, TimeUnit unit) 方法等待所有工作线程完成操作或超时。如果所有工作线程在指定的时间内完成操作,主线程输出获取到的所有网站内容。如果某个工作线程还没有完成操作,则主线程输出 "Timeout!"。

以上就是关于Java实现限定时间 CountDownLatch 并行场景的完整攻略和两个示例代码。

相关文章