• 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();
        }
    }
     





  • 相关阅读:
    [Mugeda HTML5技术教程之7]添加动画
    [Mugeda HTML5技术教程之6]添加元素
    [Mugeda HTML5技术教程之5] 创建新作品
    [Mugeda HTML5技术教程之4] Studio 概述
    [Mugeda HTML5技术教程之3] Hello World: 第一个Mugeda动画
    [Mugeda HTML5技术教程之2] Mugeda HTML5富媒体平台简介
    [Mugeda HTML5技术教程之1] HTML5: 生存还是毁灭
    Java对List进行分页
    Ubuntu中SSH连接搁置一段时间自动断开的问题
    Redis的学习笔记
  • 原文地址:https://www.cnblogs.com/ismallboy/p/6785302.html
Copyright © 2020-2023  润新知