要了解多线程如何工作,我使用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();
}
}
答案 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线程获取锁定,您将获得预期的结果。