Java 程序在多线程中无法使用同步方法产生预期输出

问题描述 投票:0回答:1

问题:

我正在根据 Herbert Schildt 的书《Java 完全参考第十版》学习 Java。我正在开发一个具有多个线程的 Java 程序,并且我期望输出按特定顺序排列,但我得到了不同的结果。我使用同步方法来控制对共享资源的访问,但输出的顺序与我预期的不同。

代码:

class Callme {
    synchronized void call(String msg) {
        System.out.print("[" + msg);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        }
        System.out.println("]");
    }
}

class Caller implements Runnable {
    String msg;
    Callme target;
    Thread t;

    public Caller(Callme targ, String s) {
        target = targ;
        msg = s;
        t = new Thread(this);
    }

    public void run() {
        target.call(msg);
    }
}

class Synch {
    public static void main(String[] args) {
        Callme target = new Callme();
        Caller hello = new Caller(target, "Hello");
        Caller synch = new Caller(target, "Synchronized");
        Caller world = new Caller(target, "World");

        hello.t.start();
        synch.t.start();
        world.t.start();

        try {
            hello.t.join();
            synch.t.join();
            world.t.join();
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        }
    }
}

书中的预期输出是这样的:

[Hello] [Synchronized] [World]

但是我有这个:

[Hello] [World] [Synchronized]

问题:

有人可以解释一下为什么我会看到这种行为吗?我在线程同步方面是否遗漏了一些影响执行顺序的东西?

我尝试过的:

我尝试调整 start() 和 join() 调用的顺序,但问题仍然存在。我还尝试使用 Thread 继承来创建线程,而不是实现 Runnable。

java multithreading synchronization thread-synchronization
1个回答
0
投票

有人可以解释一下为什么我会看到这种行为吗?

Java 语言规范或 Java 文档中没有任何内容表明线程将以任何特定顺序运行。 事实上,如果您重复运行代码和/或在其他平台上运行代码,您有时可以获得您期望的输出。

我在线程同步方面是否遗漏了一些影响执行顺序的东西?

不。 线程同步不在此讨论。 或者至少...您的示例实现的线程同步不包含在内。


有很多可能的方法可以使您的示例“工作”,但它们将涉及线程等待其他线程达到特定状态;即实际同步。

但是......我告诉你,让这些线程以特定顺序执行可能会破坏使用线程的意义。 (至少在this示例中)。 为了说明这一点,实现它的最简单方法是:

    Callme target = new Callme();
    Caller hello = new Caller(target, "Hello");
    Caller synch = new Caller(target, "Synchronized");
    Caller world = new Caller(target, "World");

    hello.run();
    synch.run();
    world.run();

即在当前线程而不是子线程上调用

run()

© www.soinside.com 2019 - 2024. All rights reserved.