zoukankan      html  css  js  c++  java
  • 利用ReentrantLock简单实现一个阻塞队列

    借助juc里的ReentrantLock实现一个阻塞队列结构:

    
    package demo.concurrent.lock.queue;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author sunqinwen
     * @version \: SimpleQueue.java,v 0.1 2019-01-16 14:47
     * 利用重入锁和重入锁的线程调度实现的简单阻塞队列
     */
    public class SimpleQueue {
    
        private static ReentrantLock lock = new ReentrantLock();
    
        private T[] nodes;
    
        private int tail = 0; // 入元素下标
    
        private int count = 0; // 元素个数
    
        private int head = 0; // 出元素下标
    
        public SimpleQueue(int size) {
            nodes = (T[]) new Object[size];
        }
    
        private static Condition notFull = lock.newCondition();
    
        private static Condition notEmpty = lock.newCondition();
    
        public void put(T t) {
            try {
                lock.lock();
                if (count == nodes.length) { // 队列已满,阻塞
                    System.out.println("目前队列已满,等待取值中");
                    notFull.await();
                }
                if (tail > (nodes.length - 1)) { // 当前游标值已经大于数组游标最大值了,则从0开始计算
                    tail = 0;
                }
                nodes[tail] = t; // 给当前游标位赋值
                count++; // 入元素元素个数+1
                tail++; // 游标值+1
                notEmpty.signalAll(); // 走到这里说明队列内至少有一个元素,则唤醒取值
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public T take() {
            T t = null;
            try {
                lock.lock();
                if (count == 0) { // 队列已空,等待加值
                    System.out.println("目前队列已空,等待入值中");
                    notEmpty.await();
                }
                if (head > (nodes.length - 1)) { // 若取值游标大于游标最大值,则从0开始计算
                    head = 0;
                }
                t = nodes[head]; // 拿到元素值
                nodes[head] = null; // 清空原有位置上的值
                head++; // 取值游标+1
                count--; // 元素个数-1
                notFull.signalAll(); // 走到这里说明队列至少有一个空位,则唤醒入值
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
            return t;
        }
    
    }

    以上为主要代码,下面进行简单的测试:

    
    @Test
    public void simpleQueueTest() throws Exception {
    
            executorService.execute(() -> {
                simpleQueue.put(1);
                simpleQueue.put(2);
                simpleQueue.put(3);
                simpleQueue.put(4);
                simpleQueue.put(5);
                simpleQueue.put(6);
    
                simpleQueue.put(7);
                simpleQueue.put(8);
                simpleQueue.put(9);
                simpleQueue.put(10);
                simpleQueue.put(11);
                simpleQueue.put(12);
            });
    
            Thread.sleep(5000L);
    
            executorService.execute(() -> {
    
                Integer r;
                while ((r = simpleQueue.take()) != null) {
                    System.out.println(r);
                }
            });
    
            Thread.sleep(5000L);
    }

    运行结果:

    
    目前队列已满,等待取值中
    目前队列已满,等待取值中
    1
    2
    目前队列已满,等待取值中
    3
    目前队列已满,等待取值中
    4
    5
    6
    7
    8
    9
    目前队列已空,等待入值中
    10
    11
    12
    目前队列已空,等待入值中
    
  • 相关阅读:
    ubuntu安装php的 mongodb扩展
    ubuntu安装php的 redis扩展
    Ubuntu14.04下安装Composer
    编译安装php
    RabbitMQ PHP扩展安装
    编译安装opssl
    安装卸载nginx
    本地VM安装虚拟机,使用xshell连接
    下载并破解IntelliJ IDEA(2017)
    symfony框架中使用service
  • 原文地址:https://www.cnblogs.com/hama1993/p/10365795.html
Copyright © 2011-2022 走看看