【问题标题】:How to "synchronize" threads to run one after another in order?如何“同步”线程依次运行?
【发布时间】:2021-01-11 20:24:47
【问题描述】:

我想让我的方法打印出 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

【问题讨论】:

  • 每个线程都有自己的锁,因此它们可以并行运行。您的通知的处理很难遵循 - 您可能只是忽略了一条可能的路径。
  • 如果你想要顺序执行,为什么要使用线程?

标签: java multithreading


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多