阻塞队列

摘要:
privatestaticBlockingQueuequeue=newBlockingQueue();publicsynchronizedvoidenqueue(Objectitem)throwsInterruptedException{while(list.size()==limit){wait();finalObject[]items=newObject[100];count;

阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列,下图展示了如何通过阻塞队列来合作:

阻塞队列第1张

线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素

从5.0开始,JDK在java.util.concurrent包里提供了阻塞队列的官方实现。尽管JDK中已经包含了阻塞队列的官方实现,但是熟悉其背后的原理还是很有帮助的。

阻塞队列的实现方式1

使用传统的wait,notifyall方式实现

import java.util.LinkedList;
import java.util.List;

public class BlockingQueue {
    private List list = new LinkedList();
    private int limit = 10;
    private static BlockingQueue queue = new BlockingQueue();
    public synchronized void enqueue(Object item) throws InterruptedException {
        while (list.size() == limit) {
            wait();
        }
        this.list.add(item);
        notifyAll();
    }

    public synchronized void dequeue() throws InterruptedException {
        if (this.list.size() == 0) {
            wait();
        }
        this.list.remove(0);
        notifyAll();
    }
}

阻塞队列的实现方式2

使用传统的ReentrantLock方式实现

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

class BoundedBuffer{
    final Lock        lock        = new ReentrantLock();
    final Condition    notFull        = lock.newCondition();
    final Condition    notEmpty    = lock.newCondition();

    final Object[]    items        = new Object[100];
    int  putptr, takeptr, count;

    public void put(Object x) throws InterruptedException{
        lock.lock();
        try{
            while (count == items.length){
                notFull.await();
            }
            items[putptr] = x;
            if(++putptr == items.length){
                putptr = 0;
            }
            ++count;
            notEmpty.signal();
        }
        finally{
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException{
        lock.lock();
        try{
            while (count == 0){
                notEmpty.await();
            }
            Object x = items[takeptr];
            
            if(++takeptr == items.length){
                takeptr = 0;
            }
            --count;
            notFull.signal();
            return x;
        }
        finally{
            lock.unlock();
        }
    }
}

免责声明:文章转载自《阻塞队列》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇LINUX下查找大文件及大的文件夹Linq to sql 有什么办法可以实现消除列重复?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

mysql 统计行数count(*)

myIsam引擎把一个表的总行数存在了磁盘上,因此执行count(*)会直接返回结果,效率很高   #但是myisam不支持事物 innodb引擎需要把数据一行行从引擎里读出来,然后计数累加。 innodb由于多版本并发控制机制,同一时刻不同回话拿到的结果可能都不相同,所以不能直接将总行数存储在磁盘上。 比如同一时刻执行了三个会话 : A会话:  sele...

linux 2.6 互斥锁的实现-源码分析

http://blog.csdn.net/tq02h2a/article/details/4317211 看了看linux 2.6 kernel的源码,下面结合代码来分析一下在X86体系结构下,互斥锁的实现原理。 代码分析 1. 首先介绍一下互斥锁所使用的数据结构:struct mutex { 引用计数器 1: 所可以利用。  小于等于0:该锁已被获取,需...

iOS 多线程

经常听到这样的问题 "你在处理多线程的时候 遇到过什么问题 或者说 你使用过多线程吗 如何操作的" 具体 我也没听过 别人是怎么回答的,我也没太想好怎样回答才算全面,今天利用工作空余时间好好系统学一下,从以下几个角度学习 1 理论 2 举例子运用 3 实际开发注意要点 一 理论   1 线程和进程       a 一般运行一个程序就是一个进程. 一个程序至...

RabbitMQ双活实践(转)

有货RabbitMQ双活实践   消息服务中间件在日常工作中用途很多,如业务之间的解耦,其中 RabbitMQ 是比较容易上手且企业使用比较广泛的一种,本文主要介绍有货在使用 RabbitMQ 的一些实践与尝试。 有货的 RabbitMQ 部署架构采用双中心模式,在两套数据中心中各部署一套 RabbitMQ 集群,各中心的 RabbitMQ 服务除了需要...

双向广度优先搜索

双向广度优先搜索 双向广度优先搜索是对广搜算法的一种扩展。广搜以起点以广度优先的顺序不断扩展,直到遇到目的节点。 而双向广搜算法从两个方向开展广搜,一个从起点,另一个从终点。 直到一个扩展队列中出现了另一个队列中已经扩展了的点,也就是说两个扩展方向出现了交点。 双向广搜相对于广搜算法来说,由于采用了双向同时扩展的方式,搜索树的宽度明显减宽,时间和空间复杂度...

Nginx事件管理之epoll模块

1. epoll 原理 假设有 100 万用户同时与一个进程保持着 TCP 连接,而每一时刻只有几十个或几百个 TCP 连接时活跃的(接收到 TCP 包),也就是说,在每一时刻,进程只需要处理这 100 万连接中的一小部分连接。 select 和 poll 的做法是:进程每次收集事件的连接(其实这 100 万连接中的大部分都是没有事件发生的)都把这 100...