使用ReentrantLock和Queue的生产者消费者

时间:2016-10-13 14:00:20

标签: java multithreading

要了解多线程如何工作,我使用Queue和ReentrantLock来模拟生产者和消费者问题。我的生产者线程正在将数据添加到队列中,但消费者没有删除。我不确定我是否正确实施了它。我知道这已被问到,但他们没有帮助。

包并发;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


class Producer implements Runnable{
    Queue<Integer> list;
    Condition con;
    ReentrantLock lock;
    int size;


    Producer(Queue q1, Condition con, ReentrantLock l1,int size)
    {
        this.list=q1;
        this.con=con;
        this.lock=l1;
        this.size=size;
    }

    public void run()
    {
        for(int i =0;i<20;i++)
        {
            if(lock.tryLock())
            {
                while(list.size()==size)
                {
                    try 
                    {
                        con.await();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                list.add(i);
                System.out.println("Producer "+ Thread.currentThread() +"added "+i+" to the List" );
                con.signalAll();
                lock.unlock();

            }
        }
    }
}


class Consumer implements Runnable{
    Queue<Integer> list;
    Condition con;
    ReentrantLock lock;
    int size;

    Consumer(Queue q1, Condition con, ReentrantLock l1,int size)
    {
        this.list=q1;
        this.con=con;
        this.lock=l1;
        this.size=size;
    }

    public void run()
    {

        for(int innerLoop =0;innerLoop<20;innerLoop++){
            if(lock.tryLock()){
                while(list.size()<1){
                    try {
                        con.await();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                int i = (int) list.remove();
                System.out.println("Consumer "+ Thread.currentThread() +"removed "+i+"  from the List" );
                con.signalAll();
                lock.unlock();
            }
        }
    }
}

class SharedResource {

    Queue list ;

    Condition con;
    ReentrantLock lock;
    int size;

    SharedResource()
    {
        size =20;
        this.list=new LinkedList<Integer>();
        lock = new ReentrantLock();
        this.con = lock.newCondition();


    }

    public Queue getList() {
        return list;
    }

    public void setList(Queue list) {
        this.list = list;
    }

    public Condition getCon() {
        return con;
    }

    public void setCon(Condition con) {
        this.con = con;
    }

    public ReentrantLock getLock() {
        return lock;
    }

    public void setLock(ReentrantLock lock) {
        this.lock = lock;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

}

public class MYPRODUCERCONSUMER {




    public static void main(String[] args) {

        SharedResource producerCObj = new SharedResource();
        Producer producer= new Producer(producerCObj.getList(), producerCObj.getCon(), producerCObj.getLock(), producerCObj.getSize());
        Thread producerThread= new Thread(producer);
        producerThread.start();

        Consumer consumer= new Consumer(producerCObj.getList(), producerCObj.getCon(), producerCObj.getLock(), producerCObj.getSize());
        Thread consumerThread= new Thread(consumer);
        consumerThread.start();
    }

}

1 个答案:

答案 0 :(得分:1)

在您的消费者中,您尝试获取锁定:

if(lock.tryLock())

但是tryLock只有在调用时不是由另一个线程持有时才获取锁。仅仅因为你首先开始制作人,很可能它已被制作人收购。您尝试执行unlock但是下一条指令是tryLock(在循环中),因此其他线程没有任何收益。换句话说,Consumer线程几乎没有机会获取锁,因为Producer线程重新获取它。只是因为你有一个有限的循环(只有20)你的消费者才刚刚结束。

如果你添加

class Producer implements Runnable{
Queue<Integer> list;
Condition con;
ReentrantLock lock;
int size;


    Producer(Queue q1, Condition con, ReentrantLock l1,int size)
    {
        this.list=q1;
        this.con=con;
        this.lock=l1;
        this.size=size;
    }

    public void run()
    {
        for(int i =0;i<20;i++)
        {
            if(lock.tryLock())
            {
                while(list.size()==size)
                {
                    try
                    {
                        con.await();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                list.add(i);
                System.out.println("Producer "+ Thread.currentThread() +"added "+i+" to the List" );
                con.signalAll();
                lock.unlock();

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

之后

 lock.unlock();

在您的Producer循环中,您将有机会获得Consumer线程获取锁定,您将获得预期的结果。