首页 > 解决方案 > 如何“同步”线程依次运行?

问题描述

我想让我的方法打印出 4 行“Hello world!”,但我的代码似乎无法按我的意愿工作。有没有办法保证它会按照我的意愿运行?有时我得到 2 行,有时单词顺序错误,等等。有时它会按我想要的方式打印单词,但大多数情况下不会。对于我的代码中可能伤害您的眼睛的任何错误,我深表歉意,我仍在学习,因此我在这里。感谢您的任何建议。

public class PrintHelloWorld {

final Lock lock = new ReentrantLock(true);
private volatile String state = "inactive";

public void printHelloWorld() {
    LocksManager manager = new LocksManager();

    Thread t1 = new Thread(() -> {
        synchronized (manager.getObject(0)) {
            for (int i = 0; i < 4; i++) {
                System.out.print("Hello ");
                try {
                    manager.notify(1);
                    state = "running t2";
                    while(!state.equals("running t1"))
                        manager.wait(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });

    Thread t2 = new Thread(() -> {
        synchronized (manager.getObject(1)) {
            for (int i = 0; i < 4; i++) {
                System.out.print("world");
                try {
                    manager.notify(2);
                    state = "running t3";
                    while (!state.equals("running t2"))
                        manager.wait(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });

    Thread t3 = new Thread(() -> {
        synchronized (manager.getObject(2)) {
            for (int i = 0; i < 4; i++) {
                System.out.println("!");
                try {
                    manager.notify(0);
                    state = "running t1";
                    while (!state.equals("running t3"))
                        manager.wait(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    {
        t1.start();
        t2.start();
        t3.start();
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private class LocksManager {
    private volatile Object[] locks;

    public LocksManager() {
        locks = new Object[3];

        for (int i=0; i<3; i++)
            locks[i] = new Object();
    }

    public Object getObject(int number) {
        return locks[number];
    }

    public void wait(int number) throws InterruptedException {
        synchronized (locks[number]) {
            locks[number].wait();
        }
    }

    public void notify(int number) {
        synchronized (locks[number]) {
            locks[number].notify();
        }
    }

}
}

输出应如下所示:

Hello world!
Hello world!
Hello world!
Hello world!

但有时它看起来像这样:

Hello world!
Hello !
worldHello !
worldHello !
world

或这个:

Hello !
world

标签: javamultithreading

解决方案


线程应该是Asynchronous,这是您在执行中看到的行为。

如果您需要强制它们同步,请查看https://www.baeldung.com/java-executor-service-tutorial中的 Future 。您可以创建一个 List 并使用 executor 和.get方法迭代该列表以等待每个线程的结果。

我不确定您的用例,但线程是一个非常具有挑战性的主题。


推荐阅读