
一、代码:
package zz.produceandconsumer; import java.util.LinkedList; public class Storage { private final static int MAX_NUM=100; private volatile LinkedList<Object> list=new LinkedList<Object>(); public void produce(int pNum){
synchronized(list){
if(list.size()+pNum>MAX_NUM){
System.out.println("当前商品数量:"+list.size()+",欲生产数量:"+pNum+",超过最大容量:"+MAX_NUM+".");
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// while(list.size()+pNum>MAX_NUM){
// System.out.println("当前商品数量:"+list.size()+",欲生产数量:"+pNum+",超过最大容量"+MAX_NUM+".");
// try {
// list.wait();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
int i=0;
while(i<pNum){
System.out.println("欲生产:"+pNum+",list.size:"+list.size()+",最大值:"+MAX_NUM+",i:"+i);
list.add(new Object());
i++;
}
System.out.println("生产了"+pNum+"个商品,仓库中存货"+list.size()+".");
list.notifyAll();
}
} public void consumer(int cNum){
synchronized(list){
// if(cNum>list.size()){
// System.out.println("当前商品数量:"+list.size()+",欲消费数量:"+cNum+",数量不足.");
// try {
// list.wait();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
while(cNum>list.size()){
System.out.println("当前商品数量:"+list.size()+",欲消费数量:"+cNum+",数量不足.");
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i=0;
if(cNum>list.size()){
System.out.println("error");
}
while(i<cNum){
// System.out.println("size:"+list.size()+",i:"+i+",cNum:"+cNum);
list.remove();
i++;
}
System.out.println("消费了"+cNum+"个商品,仓库中存货"+list.size()+".");
list.notifyAll();
}
} }
package zz.produceandconsumer; public class Producer implements Runnable{ private Storage storage;
private int num; Producer(Storage storage,int num){
this.storage=storage;
this.num=num;
} public void produce(){
this.storage.produce(num);
} @Override
public void run() {
produce();
}
}
package zz.produceandconsumer; public class Main {
public static void main(String[] args) {
Storage storage=new Storage(); new Thread(new Producer(storage, 22)).start();
new Thread(new Producer(storage, 11)).start();
new Thread(new Consumer(storage,33)).start(); new Thread(new Consumer(storage, 40)).start();
new Thread(new Consumer(storage, 50)).start();
new Thread(new Producer(storage, 90)).start(); new Thread(new Producer(storage, 65)).start();
} }
二、运行结果:
2.1多次运行,可以看到结果:
欲生产:90,list.size:151,最大值:100,i:86
欲生产:90,list.size:152,最大值:100,i:87
欲生产:90,list.size:153,最大值:100,i:88
欲生产:90,list.size:154,最大值:100,i:89
生产了90个商品,仓库中存货155.
消费了40个商品,仓库中存货115.
消费了50个商品,仓库中存货65.
list.size大于了我们规定的最大值100.
2.2 注释Storage中的31行代码,放开63行的代码,并打开consumer中的if,关掉while;注释掉Main中15行代码,多次运行结果:
size:11,i:29,cNum:33
size:10,i:30,cNum:33Exception in thread "Thread-3" java.util.NoSuchElementException
at java.util.LinkedList.removeFirst(LinkedList.java:268)
at java.util.LinkedList.remove(LinkedList.java:683)
at zz.produceandconsumer.Storage.consumer(Storage.java:64)
at zz.produceandconsumer.Consumer.consume(Consumer.java:19)
at zz.produceandconsumer.Consumer.run(Consumer.java:24)
at java.lang.Thread.run(Thread.java:745)
size:9,i:31,cNum:33
size:8,i:32,cNum:33
消费了33个商品,仓库中存货7.
三、分析和结论:
用if判断,当下一个时间片轮转到该线程时,该线程的记录点可能已经在if条件判断之后了,故此该次执行会从if语句后开始执行。
故此会造成数组超过最大长度和删除空元素的错误。
参考资料:http://www.oschina.net/question/1245392_163830