当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Java wait()和notify()的区别用法及代码示例


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。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。