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()。
相关用法
- Java notify()和notifyAll()的区别用法及代码示例
- Java wait和sleep的区别用法及代码示例
- Java wait()和notifyall()的区别用法及代码示例
- Java super()和this()的区别用法及代码示例
- Java throw和throws的区别用法及代码示例
注:本文由纯净天空筛选整理自sanatr大神的英文原创作品 Difference Between wait() and notify() in Java。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。
