zoukankan      html  css  js  c++  java
  • java多线程 生产者消费者案例-虚假唤醒

    package com.java.juc;
    
    public class TestProductAndConsumer {
    
        public static void main(String[] args) {
            Clerk clerk = new Clerk();
            Produce produce = new Produce(clerk);
            Consumer consumer = new Consumer(clerk);
            new Thread(produce, "线程A").start();
            new Thread(consumer, "线程B").start();
            new Thread(produce, "线程AA").start();
            new Thread(consumer, "线程BB").start();
        }
    
    }
    
    // 店员
    class Clerk {
        private int product = 0;
    
        public synchronized void get() {
            while (product >= 1) {  //这里使用while 不使用if 防止虚假唤醒
                System.out.println("产品已满!");
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " : " + ++product);
            this.notifyAll();
        }
    
        public synchronized void sale() {
            while (product <= 0) {
                System.out.println("缺货!");
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " : " + --product);
            this.notifyAll();
        }
    }
    
    // 生产者
    class Produce implements Runnable {
        private Clerk clerk;
    
        public Produce(Clerk clerk) {
            this.clerk = clerk;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                clerk.get();
            }
        }
    }
    
    // 消费者
    class Consumer implements Runnable {
        private Clerk clerk;
    
        public Consumer(Clerk clerk) {
            this.clerk = clerk;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                clerk.sale();
            }
        }
    }
    • public final void wait()
                      throws InterruptedException
      Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

      The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

      As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

           synchronized (obj) {
               while (<condition does not hold>)  //为了防止虚假唤醒应该总是使用在循环中
                   obj.wait();
               ... // Perform action appropriate to condition
           }
       
      This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.

    可以使用 Lock 及 Condition 改写上述代码

    package com.java.juc;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class TestProductAndConsumer {
    
        public static void main(String[] args) {
            Clerk clerk = new Clerk();
            Produce produce = new Produce(clerk);
            Consumer consumer = new Consumer(clerk);
            new Thread(produce, "线程A").start();
            new Thread(consumer, "线程B").start();
            new Thread(produce, "线程AA").start();
            new Thread(consumer, "线程BB").start();
        }
    
    }
    
    // 店员
    class Clerk {
        private int product = 0;
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        
        public void get() {
            lock.lock();
            try {
                while (product >= 1) {  //这里使用while 不使用if 防止虚假唤醒
                    System.out.println("产品已满!");
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + " : " + ++product);
                condition.signalAll();
            } finally {
                lock.unlock();
            }
        }
    
        public void sale() {
            lock.lock();
            try {
                while (product <= 0) {
                    System.out.println("缺货!");
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + " : " + --product);
                condition.signal();
            } finally {
                lock.unlock();
            }
        }
    }
    
    // 生产者
    class Produce implements Runnable {
        private Clerk clerk;
    
        public Produce(Clerk clerk) {
            this.clerk = clerk;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                clerk.get();
            }
        }
    }
    
    // 消费者
    class Consumer implements Runnable {
        private Clerk clerk;
    
        public Consumer(Clerk clerk) {
            this.clerk = clerk;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                clerk.sale();
            }
        }
    }
  • 相关阅读:
    看代码所学1
    金额,重量,成绩不使用浮点数来表示,而使用整形
    安全风控的CAP原理和BASE思想
    Git操作
    项目上线规范以及一些词汇
    水滴筹面试
    Sping框架中的注解详解
    Restful技术
    @crossorigin注解跨域
    解决Ubuntu14.04下vi编辑器不能使用方向键和退格键问题
  • 原文地址:https://www.cnblogs.com/wq3435/p/6363867.html
Copyright © 2011-2022 走看看