java - 线程代码演练,Thread.Sleep() 的机制

标签 java multithreading thread-sleep

我无法理解为什么这段代码在多次运行后打印“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.sleept的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/

相关文章:

java - 将 Spring JDBC 创建的模式设置为默认模式

java - 将字符串的第二个索引与数组字符串中下一个字符串的第二个索引进行比较

java - Java中使用try-catch处理输入异常

java - Java 中套接字的替代解决方案

java - 如何强制 JTextArea 可编辑、可点击并立即刷新输出?

java - Java中每种类型的对象类

c# - 新线程导致 "Method Name Expected"错误

android - Android蓝牙低功耗回调(LeScanCallBack)在单独的线程上?

java - 如何实现一个可以依次执行或随时停止的作业列表?

c++ - 防止 sleep_for 阻塞后台线程