感谢博主:http://zy19982004.iteye.com/blog/1626916 这篇博文给予我线程知识很大的帮助
知识背景:(1)wait()、notify()均是Object的方法,故每个对象都拥有这2个方法。
(2)obj.wait、obj.notify必须在synchronized(obj){}代码块内部使用
(3)obj.wait会抛异常,obj.notify没有异常抛出
(4)2个线程同时运行,线程1执行到obj.wait()代码时,线程阻塞,释放对象锁;线程2拿到对象锁,线程2执行到obj.notify()代码时,唤醒线程1,线程1进入锁池,此时线程2并未释放对象锁,代码继 续obj.notify()往下走,走完synchronized代码块后,线程2释放对象锁;线程2进入锁池中与线程1一起参与资源(对象锁)争抢。
(5)下面的例子中,如果线程1(生产者)obj.notify();代码注释掉,会出现线程死锁。原因:线程2执行到obj.wait(),线程2进入等待队列中;线程1,拿到对象锁,走完代码块,因为线程2还是等待,线程1一定拿到对象锁,然后执行了obj.wait();2个线程都等待了,线程死锁。
class Info { private String name; private String content; private boolean flag; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } class Producer implements Runnable { private Info info; public Producer(Info info) { this.info = info; } @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e1) { e1.printStackTrace(); } boolean flag = false; for (int i = 0; i < 10; i++) { if (!flag) { synchronized (info) { if (info.isFlag()) { try { System.out.println("有产品(MLDN),生产者等待消费...."); info.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.info.setName("李兴华"); try { Thread.sleep(90); } catch (InterruptedException e) { e.printStackTrace(); } this.info.setContent("教学老师 + " + i); flag = true; info.setFlag(true); System.out.println("set()--李兴华&&java讲师 flag=" + info.isFlag()); info.notify(); } } else { synchronized (info) { if (info.isFlag()) { try { System.out.println("有产品(李兴华),生产者等待消费...."); info.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.info.setName("MLDN"); try { Thread.sleep(90); } catch (InterruptedException e) { e.printStackTrace(); } this.info.setContent("WWW.MLDN.CN + " + i); flag = false; info.setFlag(true); System.out.println("set()--MLDN&&WWW.MLDN.CN flag=" + info.isFlag()); info.notify(); } } } } } class Consumer implements Runnable { private Info info; public Consumer(Info info) { this.info = info; } @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (info) { if (!info.isFlag()) { try { System.out.println("没有产品,等待生产...."); info.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(this.info.getName() + "————>"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.info.getContent() + "--" + i); info.setFlag(false); info.notify(); } } } } public class Test_producer_consumer { public static void main(String[] args) { Info info = new Info(); Producer p = new Producer(info); Consumer c = new Consumer(info); Thread t1 = new Thread(p, "p"); Thread t2 = new Thread(c, "c"); t1.start(); t2.start(); } }
结果有上面2种,第一种,当线程1运行到obj.notify();//a处,线程2被唤醒,线程2进入竞争obj对象的锁池。线程1执行完synchronized代码块后,释放对象锁;如果线程1不再参与对象锁的竞争那么结果2中的情况不会发生;但是结果2发生了,线程1再一次拿到对象锁,然后执行到obj.wait()方法后,释放对象锁,线程1进入阻塞状态,线程2获得对象锁。
这个结果是去掉消费者Thread.sleep(5000);得到的一种结果。2个1出现说明,线程1调用obj.notify()后,线程1再一次参与了对象锁的竞争,并且获得到了。