使用 thread.sleep() 进行轮询是如何工作的?

问题描述 投票:0回答:2

我是 Java 线程的新手,我正在尝试了解它们是如何工作的;考虑以下代码:

public class ZooInfo {
private static int counter = 0;

public static void main(String args[]) throws InterruptedException {    

    new Thread(() -> {
        for(int i=0; i<500; i++) ZooInfo.counter++;
        }).start();
    
    while(ZooInfo.counter<100) {
        System.out.println("Not reached yet");
    Thread.sleep(1000);
    }
    
    System.out.println("Reached!");
}   
}

上述代码的输出:

Not reached yet
Reached!

我不明白为什么输出只打印一次“尚未达到”,而不是每次计数器都小于 100。我期望输出打印“尚未达到”100,然后打印“已达到”?

java multithreading polling
2个回答
3
投票

我不明白为什么输出仅打印一次“尚未达到”,而不是每次计数器都小于 100。” - 确实如此!然而,

ZooInfo.counter
的值每秒仅检查一次。线程启动(对于前 100 次迭代,
new Thread(() -> { for(int i=0; i<500; i++) ZooInfo.counter++; }).start();
将花费不到一秒的时间。删除
Thread.sleep(...)
并不一定会改变行为(对我来说,它会导致
Not yet reached!
被打印 1-3 次)。这是因为新创建的线程仍然领先,而且两个线程不会“一致”运行,即一个线程可能会运行得更快。或者比另一个慢。

此外,正如 @Amongalen@Polygnome 所指出的,打印到

System.out
速度很慢。我们可以通过使用
StringBuilder
:

来改进这一点
final String lineSeparator = System.lineSeparator();
new Thread(() -> {
    for (int i = 0; i < 500; i++) ZooInfo.counter++;
}).start();

final StringBuilder builder = new StringBuilder();
while (ZooInfo.counter < 100) {
    builder.append("Not reached yet").append(lineSeparator);
}

builder.append("Reached!");
System.out.println(builder.toString());

这将增加打印

Not reached yet!
的次数。

Ideone 演示


备注:字段

private static int counter = 0;
也应该声明
volatile
以保证线程之间正确的可见性。


0
投票

你可以使用

Thread.yield()

而不是睡觉。

如果一个线程希望停止执行,为其他同等优先级的线程提供机会,那么我们应该选择yield方法。因为Thread.sleep会阻塞主线程。

© www.soinside.com 2019 - 2024. All rights reserved.