二 : ArrayBlockingQueue 数组阻塞队列

来源:互联网 发布:北京同德软件 编辑:程序博客网 时间:2024/05/30 23:33


1. 数组阻塞队列 ArrayBlockingQueue

ArrayBlockingQueue 类实现了 BlockingQueue 接口。

ArrayBlockingQueue 是一个有界的阻塞队列, 其内部实现是将对象放到一个数组里 。在读写操作上都要锁住整个容器,次队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不保证访问者公平的访问队列。所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,在队列可用时,可以按照阻塞的先后顺序访问队列,既先阻塞的生产者线程可以优先插入元祖。但是由于维护这种公平,系统会降低吞吐量。

该实现类有两个构造函数 , 一个用来指定线程的个数并且默认不适用公平访问队列 , 第二个用来指定线程以及是否使用公平策略




从构造方法可看出 , 初始话了 capacity 大小的数组,并初始化了用于判断数组是否为空,以及数组是否已满的锁。


2. 接下来看该类的 put  方法。




put方法先检测传入的资源是否为空,为空的话为抛出空指针 。count是一个int类型的整型,表示数组中资源的总个数,每当put进数组中一个资源时,count加一 ,当count数值等于数组长度时。则存的锁休息,进入阻塞状态,直到数组中的资源个数小于数组长度时,才可以将资源插入数组。  putIndex也是int类型,用作数组的下标 ,从零开始,当道到数组长度时归零,避免数组越界。

插入的过程为,创建一个新的数组指向资源数组,并将新的资源插入到数组中 ,当数组下标达到数组长度时则将下标归零,数组资源个数加一 ,并且唤醒取的锁。


3. 该实现类的 take 方法



取元素时,先判断数组资源是否为空,如果为空则取的锁等待,进入阻塞状态,等待put操作结束后唤醒该操作。 如果有资源的话,则进行取值。

takeIndex是int类型的值,初始值为0 ,当取元素的时候从0开始取,这也表明了,是以FIFO的方式进行取值。


4. 使用该实现类

public class ArrayBlokingQueue
{
static Logger logger = LogManager.getLogger();


static class Producer implements Runnable
{
private BlockingQueue<Integer> queue = null;


public Producer(BlockingQueue<Integer> queue)
{
this.queue = queue;
}


@Override
public void run()
{
while (true)
{
try
{
int num = ThreadLocalRandom.current().nextInt(100);
logger.warn("Producer create:" + num);
//当队列达到容量时候,会自动阻塞的  
queue.put(num);
if (queue.size() == 3)
{
logger.warn("Queue is full");
}
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(5));
}
catch (InterruptedException e)
{
logger.error(e);
}
}
}
}


static class Consumer implements Runnable
{
private BlockingQueue<Integer> queue = null;


public Consumer(BlockingQueue<Integer> queue)
{
this.queue = queue;
}


@Override
public void run()
{
while (true)
{
try
{
//当队列为空时,也会自动阻塞 
Integer num = queue.take();
logger.warn("Consumer take:" + num);
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(5));
}
catch (InterruptedException e)
{
logger.error(e);
}
}
}
}


public static void main(String[] args)
{
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(3,true);


new Thread(new Producer(queue)).start();
new Thread(new Consumer(queue)).start();
}


}


1 0
原创粉丝点击