什么是轮询,它有什么问题?
反复测试条件直到其变为真的过程称为轮询。
轮询通常是借助循环来实现的,以检查特定条件是否为真。如果为真,则将采取某些措施。这浪费了许多CPU周期,并使实现效率低下。
例如,在一个经典的排队问题中,一个线程正在产生数据而另一个线程正在消耗数据。
Java多线程如何解决这个问题?
为了避免轮询,Java使用三种方法,即wait(),notify()和notifyAll()。
所有这些方法最终都属于对象类,因此所有类都具有它们。它们只能在同步块中使用。
- wait()-它告诉调用线程放弃锁定并进入睡眠状态,直到其他线程进入同一监视器并调用notify()为止。
- notify()-唤醒一个在同一对象上调用wait()的单个线程。应该注意的是,调用notify()实际上并没有放弃对资源的锁定。
- notifyAll()-唤醒同一对象上所有调用wait()的线程。
一个简单的Java程序来演示这三种方法
输出:
producer thread running Waiting for return key. Return key pressed Resumed
如果您仍然对为什么我们在消耗线程中使用了通知感到困惑,请尝试将其删除并再次运行您的程序。正如您现在必须已经注意到的那样,该程序永远不会终止。
这样做的原因很简单-当您在生产线程上调用wait时,它继续等待并且从未终止。由于程序一直运行到其所有线程终止,因此它将一直运行。
解决这个问题还有第二种方法。您可以使用wait()的第二种变体。
void wait(long timeout)
这将使调用线程仅在指定的时间内休眠。