一、代码:

 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

  

  

  

多线程为何用while判断条件,而不用if。的更多相关文章

  1. Nginx中if语句中的判断条件

    一.if语句中的判断条件(nginx) 1.正则表达式匹配: ==:等值比较; ~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写: ~*:与指定正则表达式模式匹配时返回“真”,判 ...

  2. if语句中的判断条件(nginx)

    if语句中的判断条件   正则表达式匹配:     ==:等值比较;     ~:与指定正则表达式模式匹配时返回"真",判断匹配与否时区分字符大小写:     ~*:与指定正则表达 ...

  3. ThinkPHP3.2中if判断条件是两个变量

    <select name="typeId"> <foreach name="typeInfo" item="v"> ...

  4. SQL语句Where中使用别名作为判断条件

    当我们使用某个表达式作为输出的一列时,我们无法再Where条件中直接使用该列作判断条件.   例如下面的SQL语句: select id, (c1 + c2) as s from t1  where ...

  5. .Net程序员之Python基础教程学习----判断条件与循环[Fourth Day]

        今天学习Python的判断条件与循环操作. 一. 布尔变量: 在学习判断条件之前必须的了解bool变量,在Python中bool变量与C语言比较类似,与.net差别比较大,其中下面集中情况需要 ...

  6. excel如何用公式判断单元格的值是否为数字、英文、中文,以及相应的计数

    一.excel如何用公式判断单元格的值是否为数字.英文.中文. A列为数据列,B列为判断列=LOOKUP(CODE(ASC(A1)),{48,65,123;"数字","英 ...

  7. Shell脚本IF条件判断和判断条件总结

    转自:http://m.jb51.net/article/56553.htm 这篇文章主要介绍了Shell脚本IF条件判断和判断条件总结,本文先是给出了IF条件判断的语法,然后给出了常用的判断条件总结 ...

  8. 360极速浏览器UA怪异以及如何用js判断360浏览器

    本文最后一次更新于7个月前,文章内容可能略有出入.若发现文章中有错误之处,可以留言评论告诉作者. 1.360极速浏览器UA因域名不同而异 今天在写一个判断浏览器.浏览器版本.操作系统.操作系统版本.浏 ...

  9. MyBatis 判断条件为等于的问题

    在用MyBatis操作数据库的时候相信很多人都用到,当在判断null, 大于,大于等于,小于,小于等于,不等于时估计很多都用到,比较容易实现了,这里就省略了,但唯独判断条件为等于时估计蛮多人遇到坑了, ...

随机推荐

  1. 数据接口管理工具 thx RAP

    RAP是数据接口管理工具.在开发时前端将请求转至RAP,由RAP提供模拟数据:而后端使用RAP测试接口的正确性.这样RAP就成为了开发过程中的强 依赖,进而确保接口文档的实时正确性.RAP采用JSON ...

  2. ManagementFactory cannot be resolved

    ManagementFactory cannot be resolved 问题描述: (1)ManagementFactory cannot be resolved or (2)Type The ty ...

  3. 手机App开发

    /* * 登录:输入 */ public void login(String user, String pwd, TextHttpResponseHandler responsehandler) { ...

  4. php 同步因子的并发处理

    在php中,如果处理支付时,会涉及到并发. 具体体现在同步通知支付结果和异步通知结果. 拿支付宝来说,同步通知call_back和异步通知notify是没有固定先后顺序的. 有可能notify先通知到 ...

  5. Android中Service的使用详解和注意点(LocalService)

    Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...

  6. 详解Android首选项框架ListPreference

    详解Android首选项框架ListPreference 原文地址 探索首选项框架 在深入探讨Android的首选项框架之前,首先构想一个需要使用首选项的场景,然后分析如何实现这一场景.假设你正在编写 ...

  7. C# WinForm开发系列 - ComboBox

    5.一个带CheckBox,分组,颜色标记等功能的下拉框  PowerComboBoxCSharp.rar 包含自动完成下拉框,字体下拉框,电脑盘符,多列下拉框,带CheckBox,树型下拉框等.代码 ...

  8. [转]oracle for update和for update nowait的区别

    1概念小结:(针对以下引用区域内容) 1.1 普通select语句不加锁. 1.2 for update和for update nowait都试图将符合条件的数据加上行级锁.用于排斥其他针对这个表的写 ...

  9. (转)ORACLE触发器详解

    本文转载自:http://blog.csdn.net/indexman/article/details/8023740/ ORACLE PL/SQL编程之八: 把触发器说透 本篇主要内容如下: 8.1 ...

  10. Python函数,参数,变量

    func1.py def sayHello(): print ('hello world') sayHello() func_parm.py def printMax(a,b): if a>b: ...