生产者与消费者问题研究

来源:互联网 发布:中博软件学院 编辑:程序博客网 时间:2024/06/01 10:32

首先模拟单缓冲区生产者和消费者问题,wait()通常都要放入synchronized修饰的语句块中或者方法中,唤醒该线程需要调用同一对象的notify()或者notifyAll()方法

当调用某个对象notify()方法时,将从该对象等待集合中选择一个等待的线程唤醒,唤醒的线程将从等待集合中删除。

notifyAll是唤醒所有线程,只不过由于synchronized,最终只有一个线程进入

class basket{private boolean empty;private int good;public basket(){empty=true;//一开始篮子是空的}public synchronized void put(int value){//放入重量为value的内容while(!empty){//当篮子不为空时try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}good=value;System.out.println("往篮子里面放入"+good);empty=false;notify();}public synchronized void get(){//取物品while(empty){try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println("从篮子里面获得"+good);empty=true;notify();}}class producer implements Runnable{private basket b=new basket();public producer(basket b){this.b=b;}public void run(){ for (int i=1;i<=10;i++) b.put((int)(Math.random()*100));}}class consumer implements Runnable{ private basket b=new basket(); public consumer(basket b){ this.b=b; } public void run(){for (int i=1;i<=10;i++) b.get(); }}public class test8 {public static void main(String[] args) { basket b=new basket(); producer p=new producer(b); Thread t1=new Thread(p); consumer c=new consumer(b); Thread t2=new Thread(c); t1.start(); t2.start();}  }
对于多缓冲区需要借助循环队列来实现存储

class basket2{private int []a;//存储缓冲区private int front;//队首private int rear;//队尾public basket2(){//初始化存储区a=new int[10];front=0;rear=0;}public boolean isEmpty(){return front==rear;}public boolean isfull(){return (front+1)%10==rear;}public synchronized void put(int goods){//为满的时候循环等待while(isfull()){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}      front=(front+1)%10;      a[front]=goods;      System.out.println("生产者放入"+goods);      notify();}public synchronized void get(){while(isEmpty()){try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}rear=(rear+1)%10;System.out.println("消费者取出"+a[rear]);notify(); }}class producer2 extends Thread{private basket2 b=new basket2();public producer2(basket2 b){this.b=b;}public void run(){for (int i=1;i<=100;i++)b.put((int)(Math.random()*100));}}class consumer2 extends Thread{private basket2 b=new basket2();public consumer2(basket2 b){this.b=b;}public void run(){for (int i=1;i<=100;i++)b.get();}}public class test9 {//一个生产者和消费者共用多个缓冲区 public static void main(String[] args) {basket2 b=new basket2();producer2 p=new producer2(b);consumer2 c=new consumer2(b);p.start();c.start();}}

JDK1.5之后引入条件变量:

synchronized被Lock锁替换后,对应的监视方法wait,notify,notifyAll也要用awit,signal,signalAll操作替换。

class basket2{private int []a;//存储缓冲区private int front;//队首private int rear;//队尾private Lock lock;private Condition full;private Condition empty;public basket2(){//初始化存储区a=new int[10];front=0;rear=0;lock=new ReentrantLock();empty=lock.newCondition();full=lock.newCondition();}public boolean isEmpty(){return front==rear;}public boolean isfull(){return (front+1)%10==rear;}public  void put(int goods){//为满的时候循环等待lock.lock();while(isfull()){try {full.await();} catch (InterruptedException e) {e.printStackTrace();}}      front=(front+1)%10;      a[front]=goods;      System.out.println("生产者放入"+goods);      empty.signal();      lock.unlock();}public  void get(){lock.lock();while(isEmpty()){try {empty.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}rear=(rear+1)%10;System.out.println("消费者取出"+a[rear]);full.signal();    lock.unlock(); }}class producer2 extends Thread{private basket2 b=new basket2();public producer2(basket2 b){this.b=b;}public void run(){for (int i=1;i<=100;i++)b.put((int)(Math.random()*100));}}class consumer2 extends Thread{private basket2 b=new basket2();public consumer2(basket2 b){this.b=b;}public void run(){for (int i=1;i<=100;i++)b.get();}}public class test9 {//一个生产者和消费者共用多个缓冲区 public static void main(String[] args) {basket2 b=new basket2();producer2 p=new producer2(b);consumer2 c=new consumer2(b);p.start();c.start();}}

java并发库中有一些线程安全的集合,比如可以使用ConcurrentLinkedDeque()来解决多缓冲区的生产者和消费者问题。

class basket3{  private ConcurrentLinkedDeque<Integer>list=new ConcurrentLinkedDeque<Integer>();  public void put(int n){  list.add(n);  System.out.println("向列表中装入"+n);  }  public void get(){  while(!list.isEmpty())  System.out.println("从列表中移除"+list.pollFirst());  }}class Producer2 implements Runnable{basket3 b=new basket3();public Producer2(basket3 b){this.b=b;}public void run(){for (int i=1;i<=10;i++)b.put((int)(Math.random()*100));}}class Consumer2 implements Runnable{basket3 b=new basket3();private Thread t;public Consumer2(basket3 b,Thread t1){this.b=b;t=t1;}public void run(){try {t.join();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}for (int i=1;i<=10;i++)b.get();}}  public class test10 {  public static void main(String[] args) {basket3 b=new basket3();Thread t1=new Thread(new Producer2(b));Thread t2=new Thread(new Consumer2(b,t1));t1.start();t2.start();}}


0 0