最近在研究wait和notify方法,发现有个地方要注意,但是网上又说得不是很明白的地方,就是经典的生产者和消费模式,使用wait和notify实现,判断list是否为空的这个为什么要用while而不能使用if呢?其实是因为当线程wait之后,又被唤醒的时候,是从wait后面开始执行,而不是又从头开始执行的,所以如果用if的话,被唤醒之后就不会在判断if中的条件,而是继续往下执行了,如果list只是添加了一个数据,而存在两个消费者被唤醒的话,就会出现溢出的问题了,因为不会在判断size是否==0就直接执行remove了。但是如果使用while的话,从wait下面继续执行,还会返回执行while的条件判断,size>0了才会执行remove操作,所以这个必须使用while,而不能使用if来作为判断。

    以下代码是一个简单的实践,参考:http://www.cnblogs.com/hapjin/p/5492645.html(做了适当的调整)
     Add类,负责添加数据:

public class Add {
private String lock;
public Add(String lock) {
super();
this.lock = lock;
}
public void add() {
synchronized (lock) {
ValueObject.list.add("anyString");
lock.notifyAll();
}
}
}
public class ThreadAdd extends Thread {
private Add p;
public ThreadAdd(Add p) {
super();
this.p = p;
}
@Override
public void run() {
p.add();
}
}

  

 
    Subtract类,负责删除数据
public class Subtract {
private String lock;
public Subtract(String lock) {
super();
this.lock = lock;
}
public boolean check() {
System.out.println("check");
return true;
}
public void subtract() {
try {
synchronized (lock) {
if(check() && ValueObject.list.size() == 0) {//将这里的if改成while即可保证不出现越界异常!!!!
System.out.println("wait begin ThreadName="
+ Thread.currentThread().getName());
lock.wait();
System.out.println("wait end ThreadName="
+ Thread.currentThread().getName());
}
ValueObject.list.remove(0);
System.out.println("list size=" + ValueObject.list.size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadSubtract extends Thread {
private Subtract r;
public ThreadSubtract(Subtract r) {
super();
this.r = r;
}
@Override
public void run() {
r.subtract();
}
}

  

 
    封装的List队列:
public class ValueObject {
public static List list = new ArrayList();
}
 
    测试类:
public class Run {
public static void main(String[] args) throws InterruptedException {
String lock = new String("");
Add add = new Add(lock);
Subtract subtract = new Subtract(lock);
ThreadSubtract subtract1Thread = new ThreadSubtract(subtract);
subtract1Thread.setName("subtract1Thread");
subtract1Thread.start();
ThreadSubtract subtract2Thread = new ThreadSubtract(subtract);
subtract2Thread.setName("subtract2Thread");
subtract2Thread.start();
Thread.sleep(1000);
ThreadAdd addThread = new ThreadAdd(add);
addThread.setName("addThread");
addThread.start();
}
}
 

java中多线程中测试某个条件的变化用 if 还是用 while?的更多相关文章

  1. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

  2. C#中多线程中变量研究

    今天在知乎上看到一个问题[为什么在同一进程中创建不同线程,但线程各自的变量无法在线程间互相访问?].在多线程中,每个线程都是独立运行的,不同的线程有可能是同一段代码,但不会是同一作用域,所以不会共享. ...

  3. 在 Java 的多线程中,如何去判断给定的一个类是否是线程安全的(另外:synchronized 同步是否就一定能保证该类是线程安全的。)

    同步代码块和同步方法的区别:同步代码块可以传入任意对象,同步方法中 如果多个线程检查的都是一个新的对象,不同的同步锁对不同的线程不具有排他性,不能实现线程同步的效果,这时候线程同步就失效了. 两者的区 ...

  4. java中多线程中Runnable接口和Thread类介绍

    java中的线程时通过调用操作系统底层的线程来实现线程的功能的. 先看如下代码,并写出输出结果. // 请问输出结果是什么? public static void main(String[] args ...

  5. Java:多线程中的volatile

    一.为什么使用volatile 首先,通过一段简单的代码来理解为什么要使用volatile: public class RunThread extends Thread{ private boolea ...

  6. Java之多线程开发时多条件Condition接口的使用

    转:http://blog.csdn.net/a352193394/article/details/39454157 我们在多线程开发中,可能会出现这种情况.就是一个线程需要另外一个线程满足某某条件才 ...

  7. Java接口多线程并发测试 (二)

    原文地址http://www.cnblogs.com/yezhenhan/archive/2012/01/09/2317636.html 这是一篇很不错的文章,感谢原博主的分享! JAVA多线程实现和 ...

  8. C#中多线程的并行处理

    System.Threading.Tasks,在该命名空间下Task是主类,表示一个类的异步的并发的操作,创建并行代码的时候不一定要直接使用Task类,在某些情况下可以直接使用Parallel静态类( ...

  9. Java的多线程实现生产/消费模式

    Java的多线程实现生产/消费模式 在Java的多线程中,我们经常使用某个Java对象的wait(),notify()以及notifyAll() 方法实现多线程的通讯,今天就使用Java的多线程实现生 ...

随机推荐

  1. 单例模式和HttpContext线程内唯一

    单例模式 --> 多个用户会使用同一个EF,且这个EF一直不能释放,EF追踪的数据越来越多,服务器内存迟早爆炸(联想应用程序池,用户可能会用到被人用过的Application,里面的EF也是被用 ...

  2. Inno Setup卸载时注销bho

    Inno setup是一个制作安装包的免费工具,比如你用Qt开发完成一款软件,拿Inno setup打个安装包甩给客户安装就好了. 但是bho插件在注册后,万一用户卸载软件时,bho插件还是躺在管理加 ...

  3. Visual Studio 2015 Update 2 发布

    2016年3月30日,微软发布了Visual Studio 2015 Update 2 . 更新内容: Visual Studio  Visual Studio Tools for Apache Co ...

  4. performance checklist

    - embree integration                                       0w - uncompressed bvh nodes               ...

  5. linux命令之磁盘与文件系统管理命令(上)

    1.fdisk:磁盘分区工具 该命令是linux下常用的磁盘分区工具,但是只能给小于2TB的磁盘划分分区. 常用参数为-l,显示所有磁盘分区的信息. 示例: 1)显示磁盘分区列表 [root@boxi ...

  6. React Native 搭建开发环境

    1.先安装node.js,https://nodejs.org/en/download/ 然后,双击下载好的.msi文件安装即可,安装完成后,打开终端,输出npm -v 即可查看我们刚才安装的node ...

  7. 如何构建debian包

        1)安装dh_make如下: sudo apt-get intasll aptitude sudo aptitude install dh_make    2)以jsoncpp为例,说明如何生 ...

  8. 【lojg152】 乘法逆元 2(数学)

    题面 传送门 题解 orz Wa自动机 这是一个可以\(O(n)\)求出\(n\)个数逆元的方案 先把所有的数做一个前缀积,记为\(s_i\) 然后我们用快速幂求出\(s_n\)的逆元,记为\(sv_ ...

  9. MySQL 5.7.16 在CentOS 6.5 x64 安装

    1.创建MySQL组和MySQL用户   # groupadd mysql   # useradd -g mysql mysql2.创建MySQL软件安装路径/opt/software   # mkd ...

  10. vue中vueRouter使用

    首先需要安装依赖: