2 wj539h 2 wj539h_2 于 2016.05.07 06:53 提问

关于线程生产者消费者的问题

下面的程序运行的时候会一上来t2消费者线程抛异常Exception in thread "t2" java.lang.ArrayIndexOutOfBoundsException: -1
因为当t2进入等待状态的时候,t4获得所有权,马上t4又进入等待状态,唤醒之前的t2,当t2被唤醒再运行的时候已经是从bag.wait();的下一行运行,所以会抛异常。
请问怎么才能避免呢?我的bag.notify()的位置是不是放的不对呢?

public class PC1 {
public static final int limit=3;
public static void main(String[] args) {
List bag=new ArrayList();
Producer p=new Producer(bag);
Consumer c=new Consumer(bag);
Thread t1=new Thread(p,"t1");Thread t2=new Thread(c,"t2");Thread t3=new Thread(p,"t3");Thread t4=new Thread(c,"t4");
t2.start();t4.start();
t1.start();t3.start();
}
}
class Producer implements Runnable {
private List bag;
public Producer(List bag){
this.bag=bag;
}
@Override
public void run() {
synchronized(bag){
while(true){
if(bag.size()>=PC1.limit){
bag.notify();
try {bag.wait();} catch (InterruptedException e) {e.printStackTrace();}
}
int curr=bag.size();

            bag.add(++curr);
            try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+" produce "+curr);
        }
    }
}

}
class Consumer implements Runnable {
private List bag;
public Consumer(List bag){
this.bag=bag;
}
@Override
public void run() {
synchronized(bag){
while(true){
if(bag.size()<=0){
bag.notify();
try {bag.wait();} catch (InterruptedException e) {e.printStackTrace();}
}
int curr=bag.size();

            bag.remove(curr-1);
            try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+" consume "+bag.size());
        }
    }
}

}

2个回答

CSDNXIAOS
CSDNXIAOS   2016.05.07 07:02

 public class ProducerConsumerDemo{   public static void main(String [] args){    SyncStack ss=new SyncStack();    Producer p=new Producer(ss);    Consumer c=new Consumer(ss);    new Thr......
答案就在这里:线程中关于生产者与消费者的问题?
----------------------Hi,地球人,我是问答机器人小S,上面的内容就是我狂拽酷炫叼炸天的答案,除了赞同,你还有别的选择吗?

eyishion
eyishion   2016.05.08 02:47

bag.notifyAll()唤醒所有线程,bag.notify()只是唤醒某一个线程

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!