wait()和notify()是Object类的方法。将它们引入轮询的部分方式,这是反复检查要满足的条件的过程。轮询会大量浪费CPU资源,因此不是首选。
wait()具有3种变化:
1.不带任何参数的基本版本
public final void wait() // will cause thread to wait till notify is called
2.版本采用单个超时参数
public final void wait(long timeout) // will cause thread to wait either till notify is called or // till timeout (One which occurs earlier)
3.带有超时参数和纳秒参数的版本,以提高精度
public final void wait(long timeout, int nanoseconds)
notify()有1个签名
public final void notify() // Function does not take any argument
Wait() | notify() |
---|---|
在持有监视器锁的线程上调用wait()时,它将放弃监视器锁并进入等待状态。 | 在持有监视器锁的线程上调用notify()时,它表示该线程即将释放该锁。 |
一次可能有多个线程处于等待状态。 |
等待线程之一是随机选择的,并被通知。然后,被通知的线程退出等待状态并进入阻塞状态,在该状态下等待,直到前一个线程放弃了该锁并且该线程已获取了该锁。一旦获得了锁,它将进入可运行状态,在该状态下等待CPU时间,然后开始运行。 |
下面是wait()和notify()方法的演示:
Java
// Java Program to demonstrate usage of wait() and notify()
class demo {
// variable to check if part1 has returned
// volatile used to prevent threads from
// storing local copies of variable
volatile boolean part1done = false;
// method synchronized on this
// i.e. current object of demo
synchronized void part1()
{
System.out.println("Welcome to India");
part1done = true;
System.out.println(
"Thread t1 about to surrender lock");
// notify the waiting thread, if any
notify();
}
// method synchronized on this
// i.e. current object of demo
synchronized void part2()
{
// loop to prevent spurious wake-up
while (!part1done) {
try {
System.out.println("Thread t2 waiting");
// wait till notify is called
wait();
System.out.println(
"Thread t2 running again");
}
catch (Exception e) {
System.out.println(e.getClass());
}
}
System.out.println("Do visit Taj Mahal");
}
}
public class Main {
public static void main(String[] args)
{
// Make an instance of demo calss
demo obj = new demo();
// Thread t1 will call part1()
Thread t1 = new Thread(new Runnable() {
public void run() { obj.part1(); }
});
// Thread t2 will call part2()
Thread t2 = new Thread(new Runnable() {
public void run() { obj.part2(); }
});
// Start t2 and then t1
t2.start();
t1.start();
}
}
输出
Thread t2 waiting Welcome to India Thread t1 about to surrender lock Thread t2 running again Do visit Taj Mahal
各种例外
A.wait()
- 必须将wait()封装在try-catch块中,因为如果处于等待状态的线程被中断,那么它将抛出InterruptedException。
- 如果超时值是负数或纳秒值不在0到9,99,999之间,则等待住房参数的其他两个变体将引发IllegalArgumentException。
下面是异常处理的实现。
Java
// Program demonstrating occurance of InterruptedException
class demo {
volatile boolean part1done = false;
synchronized void part1()
{
System.out.println("Welcome to India");
part1done = true;
// notify() has been commented, waiting
// thread remains waiting forever notify();
}
synchronized void part2()
{
while (!part1done) {
try {
wait();
}
catch (Exception e) {
System.out.println("Exception:"
+ e.getClass());
// quit program after exception is thrown
System.exit(-1);
}
}
System.out.println("Do visit Taj Mahal");
}
}
public class Main {
public static void main(String[] args)
{
// Make an instance of demo class
demo obj = new demo();
// Thread t1 will call part1()
Thread t1 = new Thread(new Runnable() {
public void run() { obj.part1(); }
});
// Thread t2 will call part2()
Thread t2 = new Thread(new Runnable() {
public void run() { obj.part2(); }
});
// Start t2 and then t1
t2.start();
t1.start();
// This is a counter which will
// interrupt Thread t2 after 3 seconds
long startTime = System.currentTimeMillis();
while (true) {
if (System.currentTimeMillis() - startTime
> 3000)
t2.interrupt();
}
}
}
输出
Welcome to India Exception:class java.lang.InterruptedException
B.notify()
与wait()不同,notify方法不会引发InterruptedException,因此不是强制性的将其容纳在try-catch块中
注意:
- wait()和notify()都有抛出IllegalMonitorStateException的趋势
- 当线程持有对象A的监视器锁并尝试在对象B上调用wait或notify时,会发生这种情况。
- 在前面的所有示例中,方法都是在“this”上同步的,即用于调用这些方法的对象(obj)。同样,将wait()和notify()分别称为this.wait()和this.notify()(此用法是多余的)。因此,没有问题。
- 在下面的示例中,方法part1和part2现在在Integer对象上同步,但是仍在调用这些方法(obj)的对象上调用wait()和notify()。
- 这将导致IllegalMonitorStateException
下面是异常处理的实现。
Java
// Program to demonstrate IllegalMonitorStateException
class demo {
volatile boolean part1done = false;
// Made an Integer object a
// and set it randomly to 5
Integer a = 5;
void part1()
{
// Synchronized code on a
synchronized (a)
{
System.out.println("Welcome to India");
part1done = true;
// calling this.notify()
notify();
}
}
void part2()
{
// Synchronized code on a
synchronized (a)
{
while (!part1done) {
try {
// calling this.wait()
wait();
}
catch (Exception e) {
System.out.println("Exception:"+e.getClass());
System.exit(-1);
}
}
System.out.println("Do visit Taj Mahal");
}
}
}
public class Main {
public static void main(String[] args)
{
// Make an instance of demo class
demo obj = new demo();
// Thread t1 will call part1()
Thread t1 = new Thread(new Runnable() {
public void run() { obj.part1(); }
});
// Thread t2 will call part2()
Thread t2 = new Thread(new Runnable() {
public void run() { obj.part2(); }
});
// Start t2 and then t1
t2.start();
t1.start();
}
}
输出
Exception:class java.lang.IllegalMonitorStateException
要修复以上代码,只需在第19行将notify()替换为a.notify(),并在第31行将wait()替换为a.wait()。
相关用法
注:本文由纯净天空筛选整理自sanatr大神的英文原创作品 Difference Between wait() and notify() in Java。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。