为什么线程 运行 不一致?
Why don't threads run consistently?
我正在研究多线程,在 运行 一小段代码时遇到了不一致的情况。下面的代码应该打印出 123123... 但我得到的是
class RunnableDemo implements Runnable {
private String message;
RunnableDemo(String m) {
message = m;
}
public void run() {
try {
for (int i = 0; i < message.length(); i++) {
System.out.print(message.charAt(i));
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestThread {
public static void main(String args[]) throws InterruptedException {
new Thread(new RunnableDemo("1111111")).start();
new Thread(new RunnableDemo("2222222")).start();
new Thread(new RunnableDemo("3333333")).start();
}
}
Output: 123231231132123231321
Output: 123213123123213213213
Output: 123231213213231231213
我不明白的是它 运行 正确地第一次通过(打印'123')但是第二次通过它打印'231'。如果线程正在打印一个字符,则休眠 1 秒,然后重复。模式 123123... 不应该在每次我 运行 代码时保持一致,或者至少遵循前 3 个字符的模式吗?
The following code should print out 123123
不一定。基本上,您应该 永远不会 依赖线程之间没有同步的线程来唤醒并以任何特定顺序执行。
让我们先看第一个字符输出:不能保证一定是 1。是的,您首先启动线程打印 1,但这并不意味着这是第一个真正开始执行 run
的线程——或者即使它执行了,这并不意味着它是第一个执行 System.out.print
调用的线程。
考虑到相当长的睡眠时间,我会期望(但理想情况下不依赖)输出是 7 "chunks" 的序列,其中每个 "chunk" 由某些排列的字符“123”组成。但是如果你有三个线程都在 "roughly" 同时进入休眠一秒钟,你不应该期望它们一定会按 1、2、3 的顺序醒来 - 并且再次,即使他们这样做,其中一个可能会在循环体内抢占另一个。
在一台非常非常慢的机器上,即使这样的期望也是无效的 - 想象一下调用 charAt
需要 0 到 20 秒之间的随机时间 - 不太可能,但它是 可行 思想实验。那时,其中一个线程可以在另一个线程设法打印 anything.
之前抢先并完成其输出
线程被设计成独立的——如果你想让它们以协调的方式工作,你必须自己指定协调。有很多工具可以完成这项工作,但不要指望它会神奇地发生。
您无法预测CPU 一次运行哪个程序段。 运行 某些进程 CPU 将进程转换为 work
的小块。由于多个进程一次 运行。 CPU 必须根据 scheduling algorithm
实施安排。因此,简而言之,除非您以编程方式同步代码片段,否则您无法预测 CPU 接下来会做什么。
我正在研究多线程,在 运行 一小段代码时遇到了不一致的情况。下面的代码应该打印出 123123... 但我得到的是
class RunnableDemo implements Runnable {
private String message;
RunnableDemo(String m) {
message = m;
}
public void run() {
try {
for (int i = 0; i < message.length(); i++) {
System.out.print(message.charAt(i));
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestThread {
public static void main(String args[]) throws InterruptedException {
new Thread(new RunnableDemo("1111111")).start();
new Thread(new RunnableDemo("2222222")).start();
new Thread(new RunnableDemo("3333333")).start();
}
}
Output: 123231231132123231321
Output: 123213123123213213213
Output: 123231213213231231213
我不明白的是它 运行 正确地第一次通过(打印'123')但是第二次通过它打印'231'。如果线程正在打印一个字符,则休眠 1 秒,然后重复。模式 123123... 不应该在每次我 运行 代码时保持一致,或者至少遵循前 3 个字符的模式吗?
The following code should print out 123123
不一定。基本上,您应该 永远不会 依赖线程之间没有同步的线程来唤醒并以任何特定顺序执行。
让我们先看第一个字符输出:不能保证一定是 1。是的,您首先启动线程打印 1,但这并不意味着这是第一个真正开始执行 run
的线程——或者即使它执行了,这并不意味着它是第一个执行 System.out.print
调用的线程。
考虑到相当长的睡眠时间,我会期望(但理想情况下不依赖)输出是 7 "chunks" 的序列,其中每个 "chunk" 由某些排列的字符“123”组成。但是如果你有三个线程都在 "roughly" 同时进入休眠一秒钟,你不应该期望它们一定会按 1、2、3 的顺序醒来 - 并且再次,即使他们这样做,其中一个可能会在循环体内抢占另一个。
在一台非常非常慢的机器上,即使这样的期望也是无效的 - 想象一下调用 charAt
需要 0 到 20 秒之间的随机时间 - 不太可能,但它是 可行 思想实验。那时,其中一个线程可以在另一个线程设法打印 anything.
线程被设计成独立的——如果你想让它们以协调的方式工作,你必须自己指定协调。有很多工具可以完成这项工作,但不要指望它会神奇地发生。
您无法预测CPU 一次运行哪个程序段。 运行 某些进程 CPU 将进程转换为 work
的小块。由于多个进程一次 运行。 CPU 必须根据 scheduling algorithm
实施安排。因此,简而言之,除非您以编程方式同步代码片段,否则您无法预测 CPU 接下来会做什么。