java多线程 生产者和消费者 lock

  1 package com.atguigu.thread.lock;
  2 
  3 import java.util.concurrent.locks.Condition;
  4 import java.util.concurrent.locks.Lock;
  5 import java.util.concurrent.locks.ReentrantLock;
  6 
  7 /*
  8  * 小米厂家:
  9  * 库房有限,只能存10台小米电视
 10  * 工人的生产电视与销售的卖电视同时进行
 11  * 当工人生产电视把库房存满了,要求工人休息,直到销售卖出至少一台电视,库房可以再次电视,然后他再次开始生产
 12  * 当销售者把库房的电视都卖完了,要求销售者休息,直到工人生产了至少一台电视,销售才继续卖电视
 13  * 
 14  * 工人是一个线程
 15  * 销售是一个线程
 16  * 
 17  * 需要线程的通信:当工人休息后,销售组销售了电视,应该告知工人一声,可以继续生产了
 18  *            当销售休息后,工人如果生产了电视,应该通知销售,可以开始卖电视了
 19  *            
 20  * 问题:
 21  * (1)因为共享num变量,所以有线程安全问题:依靠同步解决
 22  * (2)因为库房有限:线程通信  wait,notify
 23  * 
 24  * 涉及到的方法:
 25  * (1)wait:等待
 26  * (2)notify/notifyAll:通知
 27  * 
 28  * 这两个方法必须由“锁”对象来调用
 29  * “锁”对象,必须是多个线程共享的锁对象
 30  * 
 31  * 如果是多个工人,多个销售者
 32  * 
 33  * synchronized:隐式锁
 34  * wait
 35  * notify/notifyAll
 36  * 
 37  * 如果使用Lock锁,那么线程通信应该使用Condition来解决通信
 38  * 条件.await():某种条件,等待
 39  * 条件.signal():某种条件唤醒
 40  * 
 41  */
 42 public class TestTongXin {
 43 
 44     public static void main(String[] args) {
 45         Houseware h = new Houseware();
 46         
 47         Worker w1 = new Worker(h);
 48         Worker w2 = new Worker(h);
 49         Saler s1 = new Saler(h);
 50         Saler s2 = new Saler(h);
 51         
 52         w1.start();
 53         w2.start();
 54         s1.start();
 55         s2.start();
 56     }
 57 
 58 }
 59 class Houseware{
 60     private static final int MAX_VALUE = 10;
 61     private int num = 0;
 62     private Lock lock = new ReentrantLock();
 63     private Condition full = lock.newCondition();
 64     private Condition empty = lock.newCondition();
 65     
 66     //往里放电视
 67     public void add(){
 68         lock.lock();
 69         if(num>=MAX_VALUE){
 70             try {
 71                 full.await();
 72             } catch (InterruptedException e) {
 73                 e.printStackTrace();
 74             }
 75         }else{
 76             num++;
 77             try {
 78                 Thread.sleep(100);//为了问题暴露的明显一点
 79             } catch (InterruptedException e) {
 80                 e.printStackTrace();
 81             }
 82             System.out.println("工人生产了一台电视,现在库存是:" + num);
 83 //            empty.signal();
 84             empty.signalAll();
 85         }
 86         
 87         lock.unlock();
 88     }
 89     
 90     //往外拿电视
 91     public void take(){
 92         lock.lock();
 93         if(num<=0){
 94             try {
 95                 empty.await();
 96             } catch (InterruptedException e) {
 97                 e.printStackTrace();
 98             }
 99         }else{
100             num--;
101             try {
102                 Thread.sleep(100);//为了问题暴露的明显一点
103             } catch (InterruptedException e) {
104                 e.printStackTrace();
105             }
106             System.out.println("销售卖了一台电视,现在库存是:" + num);
107             full.signalAll();
108         }
109         
110         lock.unlock();
111     }
112 }
113 
114 class Worker extends Thread{
115     private Houseware h;
116     
117     public Worker(Houseware h) {
118         super();
119         this.h = h;
120     }
121 
122     public void run(){
123         //往仓库放电视
124 //        库房.add();
125         while(true){
126             h.add();
127         }
128     }
129 }
130 class Saler extends Thread{
131     private Houseware h;
132     
133     public Saler(Houseware h) {
134         super();
135         this.h = h;
136     }
137 
138     public void run(){
139         while(true){
140             h.take();
141         }
142     }
143 }
原文地址:https://www.cnblogs.com/buxiu/p/10527035.html