我正在根据 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 语言规范或 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()
。