繁体   English   中英

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

[英]How to pause a Runnable until another of the same type completed a task?

我想创建一个程序来说明带有检查点的马拉松运动员。 创建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类的每个实例以某种方式与其他实例通信,并使整个程序休眠,直到所有Runner到达检查点。 任何“指针”都会有所帮助,谢谢!

您想要一种能够检查所有跑步者何时到达检查站的方法。 可以通过使用多个布尔变量来跟踪您的Runner是否到达checkpoint1,checkpoint2等来完成此操作。

public class Runner implements Runnable {    
    private boolean atFirstCheckpoint = false;
    // ... More checkpoint booleans 
    // ... Rest of the class

    public boolean hasReachedFirstCheckpoint() {
        return atFirstCheckpoint;
    }
}

如果我们保留了一组运行器(Array,ArrayList等),则可以创建一个方法来检查所有运行器是否都已到达检查点。

public boolean everyoneHasReachedFirstCheckpoint(Runner[] runners) {
    for (Runner r : runners) {
        if (!r.hasReachedFirstCheckpoint()) {
            return false;
        }
        return true;
    }
}

然后我们可以更改我们的arriedAt1stCheckpoint()来实现此检查。 Runner对象将休眠,直到阵列中的所有其他跑步者也都到达检查点为止。

public boolean arrivedAt1stCheckpoint(Runner[] runners) {
    this.atFirstCheckPoint = true;
    System.out.printf("Runner %d arrived at 1st checkpoint\n", runnerID);
    while (!everyoneHasReachedFirstCheckpoint(runners)) {
        sleepThread();
    }

    return true;
}

编辑:值得牢记的是,在执行while循环期间,整个运行器线程将暂停X时间,具体取决于您的sleepThread()方法。 这意味着跑步者在检查是否每个人都到达检查点之前实际上会睡X个小时,这很可能导致其他线程抢先一步。

编辑:要尝试管理您的运行程序(线程),您可能会发现使用Executor界面和/或线程池很有用。

您可能要考虑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 v / s CountdownLatch会有一些细微差别,但这应该给您入门的画面。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM