java - 如何暂停一个 Runnable 直到另一个相同类型的任务完成?

标签 java multithreading runnable

我想创建一个程序来说明马拉松运动员的检查点。创建 5 名运行者,并花费随机的时间到达第一个检查点。参赛者必须在检查点停下来,直到所有其他参赛者都到达检查点。有 2 个检查站和终点线。

这是一些我认为是实现此目的的最佳方法的基本代码:

public class Main {
public static void main(String[] args) {
    int i = 1;
    Runner[] runners = new Runner[5];

    //Create 5 Runners
    for (Runner runner : runners) {
        runner = new Runner(i++);
        runner.run();
    }

    //Wait for runners to arrive at 1st checkpoint
    for (Runner runner : runners) {
        runner.arrivedAt1stCheckpoint();
    }

    //Wait for runenrs to arrive at 2nd checkpoint
    for (Runner runner : runners) {
        runner.arrivedAt2ndCheckpoint();
    }

    //Wait for runners to finish race
    for (Runner runner : runners) {
        runner.finishedRace();
    }
}}

public class Runner implements Runnable {

    public final int runnerID;
    Random randomGenerator = new Random();

    public Runner(int i) {
        this.runnerID = i;
    }

    @Override
    public void run() {
        System.out.printf("Runner %d exists\n", runnerID);
    }

    public boolean arrivedAt1stCheckpoint() {
        sleepThread();
        System.out.printf("Runner %d arrived at 1st checkpoint\n", runnerID);
        return true;
    }

    public boolean arrivedAt2ndCheckpoint() {
        System.out.printf("Runner %d arrived at 2nd checkpoint\n", runnerID);
        sleepThread();
        return true;
    }

    public boolean finishedRace() {
        System.out.printf("Runner %d finished race\n", runnerID);
        sleepThread();
        return true;
    }

    private void sleepThread() {
        try {
            Thread.sleep(randomGenerator.nextInt(1000));
        } catch (InterruptedException ex) {
            Logger.getLogger(Runner.class.getName()).log(Level.SEVERE, null, ex);
        }
    }}

显然这只是一个结构,我错过了很多东西,所以我不要求为我编写整个程序。 我这里的主要问题是让 Runner 类的每个实例以某种方式与其他实例进行通信,并使整个程序 hibernate ,直到所有 Runner 到达检查点。 任何“指针”都会有帮助,谢谢!

最佳答案

您可能需要考虑 CyclicBarrier 或 CountDownLatch。这是使用 CyclicBarrier 的快速片段。

将屏障设置为您想要的所需计数,将屏障传递给您想要在屏障上等待的线程,如下所示

int BarrierCount = 4;
CyclicBarrier barrier = new CyclicBarrier(BarrierCount);

for (int i = 0; i <= BarrierCount; i++) {
    (new AppThreadsForBarrier(barrier, "name"+i, ...)).start();
}

现在在需要等待屏障的线程中,可以执行以下操作

class AppThreadsForBarrier extends Thread {

    // barrier along with other variables you need for your thread
    public AppThreadsForBarrier(CyclicBarrier barrier, String name, ....) {
    ..

    public void run() {
        try {
            Thread.sleep(duration);
            System.out.println(Thread.currentThread().getName() + " is calling await()");
            barrier.await();
            System.out.println(Thread.currentThread().getName() + " has started running again");
            ..

关于在哪里使用 CyclicBarrier 和 CountdownLatch 存在一些细微差别,但这应该可以让您了解如何开始使用。

关于java - 如何暂停一个 Runnable 直到另一个相同类型的任务完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42382111/

相关文章:

multithreading - 控制台应用程序 - DbContext 实例不能在 OnConfiguring 内部使用

Java - 对象值属性

java - 不要在 ajax 上重置小程序

java - ChannelInputStream 跳过方法很慢

python - 在python中使用多处理编写微分方程输出的问题

java - 使用两个线程连续读取数组

java - 基本 Java 线程和可运行模式

java - 执行每秒更新 UI 的 runnable 时出现问题

java - 如何通过 Runnable 修改事件

java - 全屏独占模式错误