注意
在同步控制方法或同步控制块里调用wait(),notify()和notifyAll()。如果在非同步控制方法里调用这些方法,程序能通过编译,但运行的时候,将得到IllegalMonitorStateException异常,并伴随着一些含糊的消息,比如"当前线程不是拥有者"。消息的意思是,调用wait(),notify()和notifyAll()的线程在调用这些方法前必须"拥有"对象的锁。当前的线程不是此对象锁的所有者,却调用该对象的notify(),notify(),wait()方法时抛出该异常。
package pro_cus; /** * 生产者 */ public class Productor extends Thread{ private Clerk clerk; private int times=0; public Productor(Clerk clerk) { this.clerk = clerk; } public void run() { synchronized(clerk) { while(times < 11) { if(clerk.pros == 5) { try { clerk.wait(); // 不能使用 wait 如果不用clerk. 则wait方法的调用者是Productor,不是当前线程的锁对象,
// 当前的线程不是此对象锁的所有者,却调用该对象的notify(),notify(),wait()方法时抛出该异常 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } clerk.pros++; clerk.notify(); //不能使用notify 不能使用 notify 如果不用clerk. 则notify方法的调用者是Productor,不是当前线程的锁对象,
// 当前的线程不是此对象锁的所有者,却调用该对象的notify(),notify(),wait()方法时抛出该异常 System.out.println("生产["+clerk.pros+"]号产品"); System.out.println("生产第["+(times+1)+"]次"); times++; } } } } package pro_cus; /** * 消费者 * @author Gary * @time 2019年8月22日 */ public class Cus extends Thread{ private Clerk clerk; private int times=0; public Cus(Clerk clerk) { this.clerk = clerk; } public void run() { synchronized(clerk) { while(times<11) { if(clerk.pros==0) { try { clerk.wait(); //不能使用wait 同理 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } clerk.pros--; clerk.notifyAll(); //不能使用 notifyAll 同理 times++; System.out.println("消费["+clerk.pros+"]号产品"); System.out.println("第["+times+"]次消费"); } } } } ------测试 package pro_cus; public class Clerk { public int pros=0; public static void main(String[] args) { Clerk clerk = new Clerk(); Productor pro = new Productor(clerk); Cus cus = new Cus(clerk); pro.start(); cus.start(); } }