【JAVA】wait和notify用法,附生产/消费模型
关于wait和notify的用法,网上已经有很多详细解释了,我只是简单的总结下。
- wait用于释放锁A,并让wait所在的线程阻塞。除非被持有锁A的其它线程执行notify来唤醒,它才能重新"活"过来。
- notify用于唤醒因为等待锁A而阻塞的线程,让它们做好竞争锁A的准备。如果有多个线程因等待锁A而被阻塞,notify只唤醒一个,唤醒所有用notifyAll。
- 参考下面的线程状态图,对理解wait和notify有很大的帮助。
总结:
- wait和notify通常和synchronized(obj)一起用,注意obj应该是多线程共用的同一个对象(即多线程状态下各个线程要竞争这个对象锁),如果不是同一个对象,那么就不能控制并发了,wait和notify也不能有效的相互作用,因为根本就不是操作同一个对象。可以参考文章最后的Demo样例。
- wait和notify来自synchronized中的obj,而不是别的地方,obj只是作为一个对象锁,供各个线程竞争。
--------------------------------
线程状态图(一样的东西,只是中英文描述而已):
--------------------------------
最后上生产/消费模型的代码:
基类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public abstract class Person implements Runnable{ 2 3 public static Object lock = new Object(); 4 public static int ticket = 0; 5 6 public abstract void execute(); 7 }
---
生产者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Producer extends Person { 2 @Override 3 public void execute() { 4 synchronized (lock) { 5 while (true){ 6 if (ticket == 0) { 7 while(ticket<10) { 8 System.out.println("生产中,当前数量:"+ticket); 9 ticket++; 10 try { 11 Thread.sleep(1000); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 } 16 System.out.println("生产完毕,当前数量:"+ticket); 17 lock.notify(); 18 }else{ 19 try { 20 lock.wait(); 21 } catch (InterruptedException e) { 22 e.printStackTrace(); 23 } 24 } 25 } 26 } 27 } 28 29 @Override 30 public void run() { 31 execute(); 32 } 33 }
---
消费者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Consumer extends Person { 2 @Override 3 public void execute() { 4 synchronized (lock){ 5 while (true){ 6 if(ticket==0){ 7 try { 8 lock.wait(); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 }else{ 13 System.out.println("消耗中,总数量:"+ticket); 14 while (ticket>0){ 15 System.out.println("消耗中,当前数量:"+ticket); 16 ticket--; 17 try { 18 Thread.sleep(1000); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } 22 } 23 System.out.println("消耗完成,当前数量:"+ticket); 24 lock.notify(); 25 } 26 } 27 } 28 } 29 30 @Override 31 public void run() { 32 execute(); 33 } 34 }
---
运行Demo
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class Demo { 2 3 public static void main(String[] args){ 4 5 //设置先生产还是先消费,默认ticket是0先生产。 6 //ticket是静态的,所以可以这么设置,虽然不是很规范。 7 new Producer().ticket = 6; 8 9 Thread pro = new Thread(new Producer()); 10 Thread con = new Thread(new Consumer()); 11 pro.start(); 12 con.start(); 13 } 14 }
重要的事再提一遍:
总结:
- wait和notify通常和synchronized(obj)一起用,注意obj应该是多线程共用的同一个对象(即多线程状态下各个线程要竞争这个对象锁),如果不是同一个对象,那么就不能控制并发了,wait和notify也不能有效的相互作用,因为根本就不是操作同一个对象。可以参考文章最后的Demo样例。
- wait和notify来自synchronized中的obj,而不是别的地方,obj只是作为一个对象锁,供各个线程竞争。
-----------------------------------------------------
请尊重作者劳动成果,
转载请注明出处:http://www.cnblogs.com/ryanyu/p/6647238.html