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

    最近在研究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();
    }
}

 

 





转载于:https://www.cnblogs.com/ismallboy/p/6785302.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值