生产者 - 消费者使用锁定和条件的问题

时间:2016-09-13 17:42:24

标签: java multithreading concurrency synchronization reentrantlock

我使用ReentrantLock和Condition实现了Producer-Consumer程序。如果我首先启动Producer线程,我的实现运行没有任何错误。但是,如果我首先启动Consumer线程,我会得到一个IllegalMonitorStateException。请指出我的计划有什么问题。

这是我的实施。

public class ProducerConsumerReentrantLock {
    public static void main(String[] args) throws InterruptedException {
        List<Integer> list = new ArrayList<Integer>(10);
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        int limit=10;

        ProductionTaskReentrantLock produce = new ProductionTaskReentrantLock(lock, condition, limit, list);
        ConsumptionTaskReentrantLock consume = new ConsumptionTaskReentrantLock(lock, condition, limit, list);

        Thread productionWorker = new Thread(produce,"Producer");
        Thread consumptionWorker = new Thread(consume,"Consumer");

        consumptionWorker.start();
        productionWorker.start();
//      consumptionWorker.start();

        productionWorker.join();
        consumptionWorker.join();
    }
}

class ProductionTaskReentrantLock implements Runnable{

    List<Integer> list = null;
    ReentrantLock lock;
    Condition condition;
    int limit;

    public ProductionTaskReentrantLock(ReentrantLock lock, Condition condition, int limit, List<Integer> list) {
        super();
        this.lock = lock;
        this.condition = condition;
        this.limit = limit;
        this.list = list;
    }

    @Override
    public void run() {
        lock.lock();
        try{
            for (int i = 0; i < 10 ; i++) {
                while(list.size()==limit){
                    try {
                        System.out.println("List is full");
                        condition.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Produced "+i);
                list.add(i);
                System.out.println(list);
                condition.signalAll();
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } finally {
            lock.unlock();
        }
    }
}

class ConsumptionTaskReentrantLock implements Runnable{

    List<Integer> list = null;
    ReentrantLock lock;
    Condition condition;
    int limit;

    public ConsumptionTaskReentrantLock(ReentrantLock lock, Condition condition, int limit, List<Integer> list) {
        super();
        this.lock = lock;
        this.condition = condition;
        this.limit = limit;
        this.list = list;
    }

    @Override
    public void run() {
        lock.lock();
        try{
            for (int i = 0; i < 10 ; i++) {
                while(list.isEmpty()){
                    try {
                        System.out.println("List is empty");
                        condition.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Consumed "+list.remove(0));
                System.out.println(list);
                condition.signalAll();
            }
        } finally {
            lock.unlock();
        }
    }

}

1 个答案:

答案 0 :(得分:0)

请参阅下面的类似示例,您应该使用await而不是wait并使用ReentrantLock返回的条件,您已经在做了。(请参阅ReentrantLock的Java文档):

package reentrant_prodcons;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Reentrant_ProdCons {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here

        Queue<Integer> queue=new LinkedList<Integer>();
        ReentrantLock lock=new ReentrantLock();
        Condition con=lock.newCondition();
        final int size = 5;

        new Producer(lock, con, queue, size).start();
        new Consumer(lock, con, queue).start();

    }

}


class Producer extends Thread{

    ReentrantLock  lock;
    Condition con;
    Queue<Integer> queue;
    int size;

    public Producer(ReentrantLock lock, Condition con, Queue<Integer> queue, int size) {
        this.lock = lock;
        this.con = con;
        this.queue = queue;
        this.size=size;
    }


    public void run(){
        for(int i=0;i<10;i++){
            lock.lock();
            while(queue.size()==size){
                try {
                    con.await();
                } catch (InterruptedException ex) {
                    Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            queue.add(i);
            System.out.println("Produced : "+i);
            con.signal();
            lock.unlock();
        }
    }

}

class Consumer extends Thread{


    ReentrantLock lock;
    Condition con;
    Queue<Integer> queue;


    public Consumer(ReentrantLock lock, Condition con, Queue<Integer> queue) {
        this.lock = lock;
        this.con = con;
        this.queue = queue;
    }

    public void run(){
        for(int i=0;i<10;i++){
           lock.lock();
           while(queue.size()<1){
               try {
                   con.await();
               } catch (InterruptedException ex) {
                   Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
               }
           }
            System.out.println("Consumed : "+queue.remove());
            con.signal();
            lock.unlock();
        }
    }
}