生产者消费者问题(多生产多消费,java实现)

生产者消费者问题有多种,本文阐述的是多个生产者生产商品,多个消费者消费商品,缓冲区中有多个商品,这种情况下应该怎么处理线程安全问题
首先,具体用一张图描述一下这种情形,达到的效果是,多个生产者一边生产,多个生产者一边消费。

生产者消费者问题(多生产多消费,java实现)_第1张图片

 需要注意两个临界情况

        1.缓冲区满的时候,生产者不能继续生产

        2.缓冲区空的时候,消费者不能继续消费

测试效果展示:

     

生产者消费者问题(多生产多消费,java实现)_第2张图片

生产者消费者问题(多生产多消费,java实现)_第3张图片

直接用代码解释实现过程会更加具体,所以看下代码实现(必要的地方都加上了注释)

  1. package ticket;
  2. import java.util.concurrent.locks.Condition;
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;
  5. //Resous类描述的是资源
  6. class Resous{
  7. //定义一个上帝类型的数组,该数组可以放多种类型的元素
  8.      final  Object[] array=new Object[100];
  9. //锁对象
  10.      private final Lock lock=new ReentrantLock();
  11. //两个监视器,notFull监视缓冲满没满,如果满了,则调用await()方法,使当前生产者线程等待,notEmpty同理
  12.      private Condition notFull=lock.newCondition();
  13.      private Condition notEmpty=lock.newCondition();
  14. //putx为生产者生产时使用的下标,takex消费者使用的下标,count为计数器,代表当前的资源数量
  15.      int putx,takex,count;
  16.      public void set(Object e) throws InterruptedException {
  17.          lock.lock();
  18.          try {
  19.              //当缓冲区满的时候,生产者停止生产,进入等待状态
  20.              while(count==array.length) {
  21.                  notFull.await();
  22.              }     
  23.            //缓冲区加入一个商品  
  24.  
  25.              array[putx]=e;
  26.             //当生产者的下标等于缓冲区的容量时,将下标置为0,重新开始生产
  27.              if(++putx==array.length)
  28.              {
  29.                  putx=0;
  30.              }
  31.              ++count;//生产完一个商品之后,计数器加一
  32.              System.out.println(Thread.currentThread().getName()+"生产者:当前容器中有"+count+"个商品");
  33.            // 唤醒一个消费者消费
  34.              notEmpty.signal();
  35.             
  36.          }finally {
  37.              //不管何种情况,最后一定要保证释放锁,避免某个线程一直持有锁资源,而使其他生产者线程处于忙等状态
  38.               //消费者线程同理
  39.              lock.unlock();
  40.          }
  41.      }
  42.     
  43.      public void get() throws InterruptedException {
  44.          lock.lock();
  45.          try {
  46.             //当缓冲区空的时候,消费者进入等待状态
  47.              while(count==0) {
  48.                  notEmpty.await();
  49.              }
  50.               //消费者从缓冲区中取出一个商品
  51.              Object e=array[takex];
  52.               //如果消费者下标值等于缓冲区长度,则将其置为0,从头开始消费
  53.              if(++takex==array.length) {
  54.                  takex=0;
  55.              }
  56.             //消费完一个商品之后,将计数器减一
  57.              --count;
  58.              System.out.println(Thread.currentThread().getName()+"消费者:当前容器中有"+count+"个商品");
  59.              //唤醒一个生产者
  60.              notFull.signal();
  61.          }finally {
  62.              lock.unlock();
  63.          }
  64.      }
  65.     
  66. }
  67. class Pro implements Runnable{
  68.     Resous r;
  69.     public Pro(Resous r) {
  70.         this.r=r;
  71.     }
  72.     @Override
  73.     public void run() {
  74.         try {
  75.             while(true) {
  76.             r.set("面包");
  77.             }
  78.         } catch (InterruptedException e) {
  79.             // TODO Auto-generated catch block
  80.             e.printStackTrace();
  81.         }
  82.         
  83.     }
  84. }
  85. class Cons implements Runnable{
  86.     Resous r;
  87.     public Cons(Resous r) {
  88.         this.r=r;
  89.     }
  90.     @Override
  91.     public void run() {
  92.         try {
  93.             while(true) {
  94.             r.get();
  95.             }
  96.         } catch (InterruptedException e) {
  97.             // TODO Auto-generated catch block
  98.             e.printStackTrace();
  99.         }
  100.         
  101.     }
  102. }
  103. //BoundBuffer 测试类
  104. public class BoundBuffer {
  105.     public static void main(String[] args) {
  106.          Resous r=new Resous();
  107.          Pro p=new Pro(r);
  108.          Cons c=new Cons(r);
  109.         
  110.          Thread t1=new Thread(p);
  111.          Thread t2=new Thread(p);
  112.          Thread t3=new Thread(c);
  113.          Thread t4=new Thread(c);
  114.         
  115.          t1.start();
  116.          t2.start();
  117.          t3.start();
  118.          t4.start();
  119.         
  120.     }
  121. }

你可能感兴趣的:(java,操作系统)