zoukankan      html  css  js  c++  java
  • java 中的阻塞队列

    1、什么是阻塞队列:

    • 支持阻塞的插入方法,意思是当队列满时,队列会阻塞插入元素的线程,知道队列不满。
    • 支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空。

      插入和移除操作的4种处理方式:

    方法/处理方式  抛出异常  返回特殊值  一直阻塞  超时退出
    插入方法 add(e) offer(e) put(e) offer(e, time, unit)
    移除方法 remove() poll() take()  poll(time, unit)
    检查方法 element() peek()  不可用  不可用

    2、java里的阻塞队列: 

    1. ArrayBlockingQueue:是一个用数组实现的有界阻塞队列。
    2. LinkedBlockingQueue:是一个永链表实现的有界阻塞队列。
    3. PriorityBlockingQueue:是一个支持优先级的无界阻塞队列。
    4. DealyQueue:是一个支持延时获取元素的无界阻塞队列。
    5. SynchronousQueue:是一个不存储元素的阻塞队列。每一个put操作必须等待一个take操作,否则不能继续添加元素。
    6. LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列。
    7. LinkedTransferQueue:是一个由链表结构组成的无界阻塞TransferQueue队列。

        重点:

        DelayQueue非常有用,可以将DelayQueue运用在以下应用场景。

      • 缓存系统的设计,可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能获取元素,标识缓存有效期到了。
      • 定时任务调度,使用DelayQueue保存当天将会执行的任务和执行时间。一旦从DelayQueue中获取到任务就开始执行,比如TimerQueue就是使用此实现的。

    3、阻塞队列的实现原理:
      使用通知模式实现。所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。查看ArrayBlockingQueue源码发现使用了Condition来实现,代码如下.

        private final Condition notEmpty;
        private final Condition notFull;
    
        public ArrayBlockingQueue(int capacity, boolean fair) {
            if (capacity <= 0)
                throw new IllegalArgumentException();
            this.items = new Object[capacity];
            lock = new ReentrantLock(fair);
            notEmpty = lock.newCondition();
            notFull =  lock.newCondition();
        }
    
        public void put(E e) throws InterruptedException {
            checkNotNull(e);
            final ReentrantLock lock = this.lock;
            lock.lockInterruptibly();
            try {
                while (count == items.length)
                    notFull.await();
                enqueue(e);
            } finally {
                lock.unlock();
            }
        }
    
        public E take() throws InterruptedException {
            final ReentrantLock lock = this.lock;
            lock.lockInterruptibly();
            try {
                while (count == 0)
                    notEmpty.await();
                return dequeue();
            } finally {
                lock.unlock();
            }
        }
        private void enqueue(E x) {
            // assert lock.getHoldCount() == 1;
            // assert items[putIndex] == null;
            final Object[] items = this.items;
            items[putIndex] = x;
            if (++putIndex == items.length)
                putIndex = 0;
            count++;
            notEmpty.signal();
        }
  • 相关阅读:
    python3 TypeError: a bytes-like object is required, not 'str'
    Centos 安装Python Scrapy PhantomJS
    Linux alias
    Vim vimrc配置
    Windows下 Python Selenium PhantomJS 抓取网页并截图
    Linux sort
    Linux RSync 搭建
    SSH隧道 访问内网机
    笔记《鸟哥的Linux私房菜》7 Linux档案与目录管理
    Tornado 错误 "Global name 'memoryview' is not defined"
  • 原文地址:https://www.cnblogs.com/gouge/p/9122123.html
Copyright © 2011-2022 走看看