【JAVA】wait和notify用法,附生产/消费模型

关于wait和notify的用法,网上已经有很多详细解释了,我只是简单的总结下。

  1. wait用于释放锁A,并让wait所在的线程阻塞。除非被持有锁A的其它线程执行notify来唤醒,它才能重新"活"过来。
  2. notify用于唤醒因为等待锁A而阻塞的线程,让它们做好竞争锁A的准备。如果有多个线程因等待锁A而被阻塞,notify只唤醒一个,唤醒所有用notifyAll。
  3. 参考下面的线程状态图,对理解wait和notify有很大的帮助。

总结:

  • wait和notify通常和synchronized(obj)一起用,注意obj应该是多线程共用的同一个对象(即多线程状态下各个线程要竞争这个对象锁),如果不是同一个对象,那么就不能控制并发了,wait和notify也不能有效的相互作用,因为根本就不是操作同一个对象。可以参考文章最后的Demo样例。
  • wait和notify来自synchronized中的obj,而不是别的地方,obj只是作为一个对象锁,供各个线程竞争。

--------------------------------

线程状态图(一样的东西,只是中英文描述而已):

--------------------------------

最后上生产/消费模型的代码:

基类

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 }
View Code

---

生产者

 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 }
View Code

---

消费者

 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 }
View Code

---

运行Demo

 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 }
View Code

 

重要的事再提一遍:

总结:

  • wait和notify通常和synchronized(obj)一起用,注意obj应该是多线程共用的同一个对象(即多线程状态下各个线程要竞争这个对象锁),如果不是同一个对象,那么就不能控制并发了,wait和notify也不能有效的相互作用,因为根本就不是操作同一个对象。可以参考文章最后的Demo样例。
  • wait和notify来自synchronized中的obj,而不是别的地方,obj只是作为一个对象锁,供各个线程竞争。

 

 

 

-----------------------------------------------------

请尊重作者劳动成果,

转载请注明出处:http://www.cnblogs.com/ryanyu/p/6647238.html

posted @ 2017-03-30 17:45  加勒比海龟  阅读(295)  评论(0编辑  收藏  举报