notify,wait,condition实现生产消费者模型

1 wait()和notify实现生产消费者模型

package com.qunar.conditionTest;

import java.util.PriorityQueue;

/**
 * Created by chen on 2018/4/22.
 */
public class Testwaitnotify {

    private int queueSize = 10;
    private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize);

    public static void main(String[] args) {
        Testwaitnotify test = new Testwaitnotify();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();

        producer.start();
        consumer.start();
    }

    class Consumer extends Thread {
        public void run(){
            consume();
        }

        private void consume(){
            while (true) {
                synchronized (queue) {  //进入同步代码块

                    while (queue.size() == 0) {//这里一定要使用while不能使用if,因为当生产者生产一个商品时,会调用notifyAll唤醒所有consumer等待线程,while保证只有一个线程能过通过,其他consumer 线程在while条件中再次被wait
                        try {
                            queue.wait();    //让当前线程等待,必须在同步代码块中执行
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            queue.notify();   //异常是唤醒当前等待线程
                        }
                    }
                    queue.poll();
                    queue.notify();    //释放当前线程持有的对象锁
                    System.out.println("从队列中取走一个元素,队列剩余"+queue.size()+"个元素");
                }
            }
        }
    }

    class Producer extends Thread {

        public void run(){
            prooduce();
        }
        private void prooduce() {
            while (true){
                synchronized(queue){

                    while (queue.size() == queueSize){ //这里也一样,必须使用while做判断语句,保证每次允许一个线程通过,其他线程在while循环中再次被wait
                        try {
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            queue.notify();
                        }
                    }
                    queue.add(1);
                    queue.notify();
                    System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
                }
            }
        }

    }

}

2 使用ReetrantLock方式实现生产消费模型

package com.qunar.conditionTest;

import java.util.PriorityQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by jw.chen on 2018/4/22.
 */
public class TestReentrantLock {

    private int queueSize = 1;
    private PriorityQueue<Integer> queue = new PriorityQueue<>(queueSize);
    private Lock lock = new ReentrantLock();  //定义ReetrantLock锁
    private Condition produceLock = lock.newCondition();  //produce条件锁
    private Condition consumeLock = lock.newCondition();   //consume条件锁

    public static void main(String[] args) {
        TestReentrantLock test = new TestReentrantLock();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();

        producer.start();
        consumer.start();
    }

    class Consumer extends Thread {
        public void run(){
            consume();
        }

        private void consume(){
            while (true) {
                lock.lock();  //condition条件锁必须在同步代码块中执行
                try {
                    while (queue.size() == 0) {
                        System.out.println("队列空,等待数据");
                        try {
                            consumeLock.await();  //队列为空时,让consume锁等待,注意这里使用的是await()不是wait()方法,
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.poll();
                    produceLock.signal();  //消费后释放produce lock,使其继续生产工作
                    System.out.println("从队列取走一个元素,队列剩余" + queue.size() + "个元素");
                }finally {
                   lock.unlock();  //finally中释放锁
                }
            }
        }
    }

        class Producer extends Thread {

        public void run(){
            prooduce();
        }
        private void prooduce() {
            while (true){
              lock.lock();
              try {

                  while (queue.size() == queueSize) {
                      try {
                          produceLock.await();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                      queue.offer(1);
                      System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
                      consumeLock.signal();
                  } finally {
                  lock.unlock();
                 }

                }
            }
        }

    }

需要注意的点

 使用条件锁,需要在Lock环境下使用,condition锁使用的wait方法是await方法,这里需要注意

  使用condition.signal()唤醒对应条件的应用

猜你喜欢

转载自blog.csdn.net/qqchenjunwei/article/details/80037089