简体   繁体   English

Java 线程 - 如何正确等待线程完成?

[英]Java threading - How to properly wait for threads to finish?

I had a test at university telling me to fix the code below, so it waits for the threads to finish before printing "END".我在大学进行了一次测试,告诉我修复下面的代码,因此它在打印“END”之前等待线程完成。 content of MyThread was unknown: MyThread 的内容未知:

Thread s1 = new MyThread();
Thread s2 = new MyThread();
s1.start();
s2.start();
s1.sleep(1000);
s2.sleep(1000);
System.out.println("END");

My solution at first was to join() the 2 threads, however that did not work.我最初的解决方案是 join() 2个线程,但这不起作用。

Thread s1 = new MyThread();
Thread s2 = new MyThread();
s1.start();
s2.start();
s1.sleep(1000);
s2.sleep(1000);
s1.join();
s2.join();
System.out.println("END");

Then I tried checking if the Threads were alive with a while loop.然后我尝试通过 while 循环检查线程是否还活着。

Thread s1 = new MyThread();
Thread s2 = new MyThread();
s1.start();
s2.start();
s1.sleep(1000);
s2.sleep(1000);
while(s1.IsAlive() || s2.IsAlive){
  continue;
}
System.out.println("END");

But this one did not work either.但是这个也不起作用。 Apperantly the correct answer was to join the threads AND remove the 2 sleeps:显然,正确的答案是加入线程并删除 2 个睡眠:

Thread s1 = new MyThread();
Thread s2 = new MyThread();
s1.start();
s2.start();
s1.join();
s2.join();
System.out.println("END");

My question is: Why are none of my answers acceptable?我的问题是:为什么我的答案都不能被接受? Asked my lab leader, but he could not give me an answer.问我的实验室负责人,但他无法给我答案。 Coded the test out at home and it seems to work just fine.在家里对测试进行编码,它似乎工作得很好。 Thanks in advance for the help!在此先感谢您的帮助!

The solution with join() is for sure correct. join()的解决方案肯定是正确的。 If we look at the official docs we can see the following ...如果我们查看官方文档,我们可以看到以下内容...

public final void join​(long millis) throws InterruptedException Waits at most millis milliseconds for this thread to die. public final void join (long millis) throws InterruptedException 最多等待 ms 毫秒让该线程死亡。 A timeout of 0 means to wait forever.超时为 0 意味着永远等待。 This implementation uses a loop of this.wait calls conditioned on this.isAlive.此实现使用以 this.isAlive 为条件的 this.wait 调用循环。 As a thread terminates the this.notifyAll method is invoked.当线程终止时,调用 this.notifyAll 方法。 It is recommended that applications not use wait, notify, or notifyAll on Thread instance建议应用程序不要在 Thread 实例上使用 wait、notify 或 notifyAll

This method was designed precisely to handle this use case.此方法专为处理此用例而设计。

The reason why you might not be getting the expected results is because of the t.sleep() calls you call on a reference to another thread, see one of the comments to the original post.您可能无法获得预期结果的原因是因为您调用了对另一个线程的引用的t.sleep()调用,请参阅对原始帖子的评论之一。

Imagine a future scenario: you now work in a bank or worse yet a nuclear power station.想象一下未来的情景:你现在在银行工作,或者更糟的是在核电站工作。 The importance of knowing precisely when those background tasks are completed is much higher.准确了解这些后台任务何时完成的重要性要高得多。

The solutions that use sleep(x) may appear to work if the task is short lived, but a sleep gives no guarantee that the operations were completed.如果任务持续时间很短,则使用sleep(x)的解决方案可能看起来有效,但 sleep 并不能保证操作已完成。 What if each MyThread takes 1 millisecond and your code is called a million times?如果每个 MyThread 需要 1 毫秒并且您的代码被调用一百万次怎么办? Using sleep(1000) means that your program will run for an excessively long time without knowing the transactions definitely ended.使用sleep(1000)意味着您的程序将在不知道事务肯定结束的情况下运行过长的时间。

The solution with while(s1.IsAlive()... may appear to work but is a fail because your calling thread is running a tight loop. It will be consuming excessive CPU because it is always running while others task are, and therefore that is at the detriment of the CPU allocated for MyThread tasks. while(s1.IsAlive()...的解决方案可能看起来有效但失败,因为您的调用线程正在运行一个紧密的循环。它将消耗过多的 CPU,因为它总是在其他任务运行时运行,因此会损害为 MyThread 任务分配的 CPU。

The correct answer uses Thread.join .正确答案使用Thread.join Your calling thread blocks - no CPU wasted - until each MyThread ends.您的调用线程会阻​​塞 - 不会浪费 CPU - 直到每个 MyThread 结束。 The elapsed time is exactly matched to their running time, and you know the MyThreads were ended.经过的时间与它们的运行时间完全匹配,您知道 MyThreads 已结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM