Java多线程操作案例-生产者和消费者实现

来源:互联网 发布:网络用语ac是什么意思 编辑:程序博客网 时间:2024/06/04 19:14

生产者和消费者问题是线程操作中的一个经典案例,本文采用Java多线程来实现这一经典问题。
1、使用Java来实现,首先要分析这个问题需要几个类来实现:
(1)这个问题本身就是一个类,即主类 ;
(2)要有生产者类和消费者类;
(3)生产什么,消费什么,所以需要一个物品类,这里使用电脑类 ,表示生产和消费电脑;
(4)多线程操作,需要对资源区的资源进行异步操作,即生产的电脑需要一个仓库存放,消费电脑也需要从这个仓库取出来,因此需要一个盛放电脑的仓库类。

2、解决这个问题要注意:
(1)生产者和消费者可能会同时对资源区(仓库)进行异步操作,会导致仓库内电脑数量不一致,因此要使用Java中的synchronized关键字对存放电脑和取出电脑的操作进行同步。
(2)如果仓库已满,则生产者线程阻塞,需要等待;如果仓库为空,则消费者线程阻塞需要等待,因此需要使用Java中的一些线程的等待和唤醒的方法。

public class Procon {            //主类    public static void main(String[] args) {          Repertory rep = new Repertory(5);//新建一个存放电脑的仓库          Producer p = new Producer(rep);//新建一个生产者对象,使用rep仓库          Consumer c = new Consumer(rep);//新建一个消费者对象,使用同一个rep仓库          Thread pt = new Thread(p);//生产者线程          Thread ct = new Thread(c);//消费者线程         pt.start();//启动生产者线程         ct.start();//启动消费者线程      }  }//电脑类  class Computer{      int id;//电脑编号    Computer(int id){          this.id = id;      }      public String getComputer(){          return "Computer:"+this.id;      }  }  //仓库类 class Repertory{      private int length; //仓库大小     private Computer[] compArrey;//具体存放电脑的位置    private int index;//仓库位置的索引    Repertory(int len){        this.length = len;        this.index = 0;        compArrey = new Computer[len];//构造电脑对象数组,在这个仓库中开辟存放电脑的空间    }      //将电脑放入仓库的方法,使用synchronized来保持仓库数据的同步     public synchronized void push(Computer c){          while(this.index == this.length){//如果仓库满了,需要生产者线程等待              try {                  this.wait();//让当前线程等待             } catch (InterruptedException e) {                   e.printStackTrace();              }          }          this.notify();//唤醒在此对象监视器上等待的单个线程,即消费者线程          this.compArrey[index] = c;          this.index++;      }      //从仓库中取出电脑     public synchronized Computer pop(){          while(this.index == 0){//如果仓库为空,需要消费者线程等待              try {                  this.wait();              } catch (InterruptedException e) {                  e.printStackTrace();              }          }          this.notify();          this.index--;          return this.compArrey[index];      }  }  //生产者类实现Runnable接口,用于构造生产者线程 class Producer implements Runnable{      private Repertory rep; //使用的仓库    Producer(Repertory rep){          this.rep = rep;      }      @Override  //重写run方法    public void run() {          // 开始生产电脑         for(int i=0;i<10;i++){              Computer c = new Computer(i);              this.rep.push(c);              System.out.println("生产了"+c.getComputer());              try {                  Thread.sleep(10);//每生产一台电脑,线程休眠10毫秒              } catch (InterruptedException e) {                  e.printStackTrace();              }          }      }  }  //消费者类实现Runnable接口,用于构造消费者线程 class Consumer implements Runnable{      private Repertory rep; //使用的仓库     Consumer(Repertory rep){          this.rep = rep;      }      @Override      public void run() {           for(int i=0;i<10;i++){//开始消费电脑             Computer c = this.rep.pop();              System.out.println("消费了"+c.getComputer());              try {                  Thread.sleep(100);//每消费一台电脑,消费者线程休眠100毫秒             } catch (InterruptedException e) {                   e.printStackTrace();              }          }      }  }