我尝试制作简单的多线程机器人。他得到了头部线和两条腿,一条腿 - 一个线程。一切都运作良好,但如何创建控制线程,控制每条腿?
我的代码是:
public class Controller implements CommandInterface{
private final Object monitor = new Object();
private int numOfSteps = 10;
class Legs implements Runnable {
private final String whichLeg;
Legs(String whichLeg) {
this.whichLeg = whichLeg;
}
@Override
public void run() {
for(int i = 0; i < numOfSteps;i++) {
synchronized (monitor) {
step();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
monitor.notify();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void step() {
System.out.println(whichLeg);
}
}
Legs left = new Legs("left feet");
Legs right = new Legs("right feet");
@Override
public void execute() {
new Thread(left).start();
new Thread(right).start();
}
}
要启动机器人我使用此类:
public class ClientInterface {
public static void main(String [] args) {
new Controller().execute();
}
}
我知道我应该使用join()
来等待另一个线程。
我希望看到这样的结果:
Init head
head sends make 1 step
left feet
head sends make 2 step
right feet
and so on...
我试图在main方法创建头部线程并调用join()
但它等待当前线程,但我需要等待leg.i尝试创建头部线程,如Thread head = new Thread(new Runnable{ tried here to run execute method });
,但它都没有'工作。
答案 0 :(得分:1)
有很多可能的选择。这是其中之一:
每条腿都成为监视器本身。当Head线程启动时,它开始通知/等待腿部。所以在第一次迭代时,头部将通知/等待第一个腿,在第二次迭代时它将通知/等待第二个腿,依此类推直到结束。腿只是循环永远等待Head线程通知。他们的工作是接收通知,打印相应的消息并向主管发送通知
这是草图:
interface CommandInterface {
void execute();
}
class Controller implements CommandInterface {
private static final int NUM_OF_STEPS = 10;
private final Legs[] legs = {
new Legs("left feet"),
new Legs("right feet")
};
@Override
public void execute() {
Executors.newSingleThreadExecutor().execute(() -> {
System.out.println("Init head");
for (Legs leg : legs) {
leg.start();
}
for (int i = 0; i < NUM_OF_STEPS; i++) {
try {
TimeUnit.SECONDS.sleep(1);
int currentLegIndex = i % legs.length;
synchronized (legs[currentLegIndex]) {
System.out.println("head sends make " + (i + 1) + " step");
legs[currentLegIndex].notify();
legs[currentLegIndex].wait();
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted!", e);
}
}
});
}
class Legs extends Thread {
private final String whichLeg;
Legs(String whichLeg) {
this.whichLeg = whichLeg;
}
@Override
public void run() {
while (true) {
try {
synchronized (this) {
this.wait();
step();
this.notify();
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted!", e);
}
}
}
private void step() {
System.out.println(whichLeg);
}
}
}
class ClientInterface {
public static void main(String [] args) {
new Controller().execute();
}
}
您也可以考虑创建共享CountDownLatch
。我会推荐阅读它的javadoc。我想你会理解这个想法并自己创造一个更优雅的解决方案;)