使用thread.sleep()进行轮询的工作原理是什么?

huangapple go评论79阅读模式
英文:

How does polling with thread.sleep() work?

问题

以下是翻译好的部分:

我不明白为什么输出仅打印一次“Not reached yet”,而不是每次计数器小于100时都打印一次。我期望输出会打印“Not reached yet”100次,然后打印“Reached”。

英文:

I am new to threads in Java, I am trying to understand how they work; considering the following code:

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!");
}	
}

The output of the above code:

Not reached yet
Reached!

I don't understand why the output prints "Not reached yet" just once, and not for every time counter is less than a 100. I was expecting the output to print "Not reached yet" a 100 then print "Reached"?

答案1

得分: 3

"我不明白为什么输出仅在计数器小于100时打印一次"尚未到达",而不是每次计数器小于100时都打印一次。 " - 实际上是这样的!但是,ZooInfo.counter的值仅在每秒钟检查一次。启动的线程(new Thread(() -> { for(int i=0; i<500; i++) ZooInfo.counter++; }).start();)在前100次迭代中所需的时间明显少于一秒。删除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,以确保线程之间有适当的可见性。

英文:

"I don't understand why the output prints "Not reached yet" just once, and not for every time counter is less than a 100." - It does! The value of ZooInfo.counter, however, is only checked once a second. The thread started (new Thread(() -> { for(int i=0; i<500; i++) ZooInfo.counter++; }).start(); will take significantly less than a second for the first 100 iterations. Removing the Thread.sleep(...) does not necessarily change the behaviour (for me, it leads to Not yet reached! being printend 1-3 times). This is due to the fact that the newly created thread still has a head start. Also, the two threads do not run "in unison", i.e. one thread may proceed faster or slower than the other.

Furthermore, as was pointed out by @Amongalen and @Polygnome, printing to System.out is slow. We can improve this by using a 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());

This will increase the number of times Not reached yet! is printed.

<kbd>Ideone demo</kbd>


A remark: the field private static int counter = 0; should also be declared volatile to guarantee proper visibility between threads.

huangapple
  • 本文由 发表于 2020年9月24日 19:12:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/64045252.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定