我是 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,然后打印“已达到”?
“我不明白为什么输出仅打印一次“尚未达到”,而不是每次计数器都小于 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!
的次数。
备注:字段
private static int counter = 0;
也应该声明 volatile
以保证线程之间正确的可见性。
你可以使用
Thread.yield()
而不是睡觉。
如果一个线程希望停止执行,为其他同等优先级的线程提供机会,那么我们应该选择yield方法。因为Thread.sleep会阻塞主线程。