我无法理解为什么这段代码在多次运行后打印“Apple”而不是“Orange”。有人可以帮忙吗?
public class Fruit {
public static String fruit;
public static void main(String args[]) throws InterruptedException {
try {
Thread t = new AppleThread();
t.start();
} catch (IllegalThreadStateException e) {
System.out.println("Thread generated an error.");
}
fruit = "Orange";
Thread.sleep(100);
System.out.println(fruit);
}
private static class AppleThread extends Thread {
@Override
public void run() {
fruit= "Apple";
}
}
}
对我来说,它的核心有两个问题: 1.) 当引用Thread.sleep(100)时它指的是哪个线程?
2.) 我们与分配 message =“orange”的主线程并行执行 t.start()。然而,苹果总是打印出什么,这是为什么呢? “Apple”似乎总是获得最后的分配。
非常感谢对此进行全面澄清。
最佳答案
1.) When referring to Thread.sleep(100) which thread is it referring to?
当前线程正在执行包含该语句的代码段。在本例中它是主线程。它给出 t
有机会做它应该做的事情,否则主线程将终止整个过程而不关心 t
完全没有。
如果你输入Thread.sleep
在t
的run方法中,然后 t 去 sleep 。
2.) why always "Apple"?
您遇到的是 main
线程创建一个新线程t
并称其为 start
方法。
但这并不意味着现在t
实际上运行,而 main 没有运行。 main
继续并行执行,直到分配后进入休眠状态 fruit = "Orange";
。
也许同时t
甚至获得了一点CPU,但不足以达到fruit= "Apple";
。仅在main
之后sleep它可以执行,所以fruit
碰巧的结果总是 Apple
,但不一定如此。
请注意,这是您的计算机/操作系统/java 应用程序现在的行为。不同情况下t
实际上可能会在 main
之前获得足够的 cpu 来完全执行完成它的任务,那么你就会剩下一个橙子。
你实际上有一个race condition内置到您的代码中,缺少 synchronization 。您现在看到的可能看起来是连续的。启动另外几个线程,使用另一个操作系统或CPU,可能会发生其他情况。这取决于线程如何 scheduled ,哪一个先绘制或何时绘制。 可能它们是并行的,甚至达到了同时写入变量的程度。这是 another discussion 。
您运行代码几次,总是得到相同的结果。运行它 100.000 次,也许总是相同的结果,只是除了一次。或者每年一次或每个系统生命周期一次。这也是为什么并发错误或竞争条件如此难以追踪的原因,每个人都避免手工制作的并发突变和同步like the plague并使用immutable data以及预调解处理,例如java 并行流,或者选择完全避免在该领域工作并种植土 bean 或其他什么。
顺便说一句。尝试输入 Thread.sleep(100);
之前fruit = "Orange";
看看接下来发生了什么。或者,也许,不是每个线程只分配一次,而是调用一个单独的方法来重复执行某些操作并产生结果,这可能会使其更加透明。它还会造成一种情况,即 2 个线程运行同一段代码。
public static void printSome() {
IntStream.range(0, 100).forEach(i -> {
System.out.println(String.format("Thread %d says:%d", Thread.currentThread().getId(), i));
Thread.yield();
});
}
关于java - 线程代码演练,Thread.Sleep() 的机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58983218/