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

Thread Code Walkthrough, mechanics of 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.) 我们与分配消息 = "orange" 的主线程并行执行 t.start()。但是,苹果打印出来的总是什么,这是为什么呢? "Apple" 似乎它总是得到最后一个分配。

非常感谢对此进行全面清理。

1.) When referring to Thread.sleep(100) which thread is it referring to?

当前执行包含该语句的代码段的线程。在这种情况下,它是主线程。它让 t 有机会做它应该做的事情,否则主线程会终止,所以整个过程根本不关心 t

如果你把Thread.sleep放在t的运行方法中,那么t就进入休眠状态。

2.) why always "Apple"?

您遇到的是 main 线程创建新线程 t 并调用其 start 方法。

但这并不意味着现在 t 实际上 运行s 而 main 不是。 main 继续并行执行,直到它在分配 fruit = "Orange"; 后进入休眠状态。

也许在此期间 t 甚至获得了一点 cpu,但还不足以达到 fruit= "Apple";。只有在 main 休眠后它才能执行,所以 fruit 碰巧总是以 Apple 结束,但不一定如此。

请注意,这是您 machine/operating system/java 应用程序目前的行为。在不同的情况下,t 实际上可能会在 main 到达其分配之前获得足够的 cpu 来完全执行,然后你将得到一个 O运行ge。

你实际上有一个race condition built into your code, which lacks synchronization. What you seen now might look sequential. Start another few threads, use another operating system or cpu and something else might happen. It depends how the threads are scheduled, which one draws first or just when. Potentially they're parallel, even to the degree that both write simultaneously to the variable. Which is another discussion

你运行你的代码重复了几次,结果总是一样。 运行 100.000 次,也许总是相同的结果,除了一次。或者每年一次或每个系统生命周期一次。这也是为什么并发错误或竞争条件如此难以追踪的原因,每个人都避免手工制作的并发突变和同步 like the plague and uses immutable data 和预调解处理,例如java 并行流,或者选择完全避免在田间工作并种植土豆或其他任何东西。

顺便说一句。尝试将 Thread.sleep(100); 放在 fruit = "Orange"; 之前,然后看看会发生什么。或者,不是每个线程只分配一次,而是调用一个单独的方法重复做某事并产生结果,这可能会使它更 t运行sparent。它还会造成一种情况,其中 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();
        });
    }