[英]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.