消费者/生产者(条件变量)

消费者/生产者(条件变量)

在这里我以画图的形式来说明它的设计思路

代码如下(代码中的注释很全,方便理解):

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import com.alibaba.fastjson.JSON;
/**
 * 条件变量Condition锁
 *
 * @author onlyone
 */
public class ConditionDemo {
     //可重入锁 也叫做递归锁 指的是同一线程 外层函数获得锁之后 (可重入锁最大的作用是避免死锁)
     //内层递归函数仍然有获取该锁的代码,但不受影响
     //在JAVA环境下 ReentrantLock和 synchronized 都是 可重入锁
    private ReentrantLock lock     = new ReentrantLock();
    //并且创建两个condition,相当于两个阻塞
    //条件变量1
    private Condition     take     = lock.newCondition();
    //条件变量2
    private Condition     put      = lock.newCondition();
    //阻塞队列(先进先出)
    private BlockingQueue queue    = new ArrayBlockingQueue<>(10000);
    // 队列的最大容量
    private int           capacity = 5;
    // 初始值
    private int           i        = 1;
   //往队列里面插入数据
    public void put() {
        lock.lock(); //获得锁
        System.out.println(String.format("【put】i=%d 获取锁!!!", i));
        try {
            //使用while的目的:它醒了之后你得用while循环让它再去判断一次条件
            while (queue.size() == capacity) {
                System.out.println(String.format("【put】插入 %d 时队列满,执行put.await!队列值:【%s】", i,
                                                 JSON.toJSONString(queue.toArray())));
                put.await();//条件阻塞
            }
            queue.put(i);
            System.out.println(String.format("【put】插入 %d 到队列", i));
            i++;
            // 读操作唤醒
            take.signal(); //条件唤醒
        } catch (Exception e) {
        } finally {
            System.out.println(String.format("【put】i=%d 释放锁!!!", i - 1));
            lock.unlock(); //释放锁 一般放在finally里
        }
    }
    /**
           * 从队列读数据
     */
    public void take() {
        lock.lock();  //获取锁
        System.out.println("【take】获取锁!");
        int data = 0;
        try {
            //使用while的目的:它醒了之后你得用while循环让它再去判断一次条件
            while (queue.size() == 0) {
                System.out.println("【take】执行take.await!");
                take.await();//条件阻塞
            }
            data = (int) queue.take();
            System.out.println(String.format("【take】从队列读取值 %d ,队列值:【%s】", data, JSON.toJSONString(queue.toArray())));
            // 写操作唤醒
            put.signal();//条件唤醒
        } catch (Exception e) {
        } finally {
            System.out.println(String.format("【take】i=%d 释放锁!!!", data));
            lock.unlock(); //释放锁 一般放在finally
        }
    }
}

测试代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestClass {
    // 写任务
    static class WriteTask implements Runnable {
        private ConditionDemo condition;
        public WriteTask(ConditionDemo condition){
            this.condition = condition;
        }
        @Override
        public void run() {
                condition.put();
        }
    }
    // 读任务
    static class ReadTask implements Runnable {
        private ConditionDemo condition;
        public ReadTask(ConditionDemo condition){
            this.condition = condition;
        }
        public void run() {
                condition.take();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ConditionDemo condition = new ConditionDemo();
        //类似于一个线程池的功能
        for (int i = 0; i < 20; i++) {
            new Thread(new WriteTask(condition)).start();;     
           }
        for (int i = 0; i < 20; i++) {
            new Thread(new ReadTask(condition)).start();;
           } 
    }
}

 效果:

发布了95 篇原创文章 · 获赞 180 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_38316697/article/details/91444084