如何创建线程来控制另一个?

时间:2017-12-01 13:44:31

标签: java multithreading

我尝试制作简单的多线程机器人。他得到了头部线和两条腿,一条腿 - 一个线程。一切都运作良好,但如何创建控制线程,控制每条腿?

我的代码是:

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 });,但它都没有'工作。

1 个答案:

答案 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。我想你会理解这个想法并自己创造一个更优雅的解决方案;)