您的位置:首页 > 产品设计 > UI/UE

ArrayBlockingQueue<生产者消费者>及方法区别

2015-11-05 11:48 721 查看
官方描述

一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素。队列的尾部 是在队列中存在时间最短的元素。新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素。

这是一个典型的“有界缓存区”,固定大小的数组在其中保持生产者插入的元素和使用者提取的元素。一旦创建了这样的缓存区,就不能再增加其容量。试图向已满队列中放入元素会导致操作受阻塞;试图从空队列中提取元素将导致类似阻塞。

此类支持对等待的生产者线程和使用者线程进行排序的可选公平策略。默认情况下,不保证是这种排序。然而,通过将公平性 (fairness) 设置为 true 而构造的队列允许按照 FIFO 顺序访问线程。公平性通常会降低吞吐量,但也减少了可变性和避免了“不平衡性”。

此类及其迭代器实现了
Collection
Iterator
接口的所有可选 方法。

此类是 Java Collections Framework 的成员。

package com.thread.arrayblockingqueue;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Apple{
private String name;
public Apple(String name){
this.name = name;
}
public String toString(){
return this.name;
}
}
class Basket{
BlockingQueue<Apple> basket = new ArrayBlockingQueue<Apple>(3);
public String add(Apple apple) throws InterruptedException{

if(basket.size() >=3){
return ",篮子已满。。等待取走";
}else{
basket.put(apple);
return "成功生产" + apple.toString();
}

}
public String sub() throws InterruptedException{
if(basket.size()<=0){
return (",已取完。。等待生产");
}else{
return ",成功取走" + basket.take().toString();
}

}
}
class Producer implements Runnable{
private Random r = new Random();
private String name;
private Basket basket;
public Producer(String name, Basket basket){
this.name = name;
this.basket = basket;
}
@Override
public void run() {
int i = 0;
while(true){
try {
System.out.println("生产者:" + name +",尝试生产。。" + basket.add(new Apple("苹果"+i++)));
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(r.nextInt(5)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

}
class Consumer implements Runnable{
private Random r = new Random();
private String name;
private Basket basket;
public Consumer(String name, Basket basket){
this.name = name;
this.basket = basket;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
System.out.println("消费者:" +name+"尝试取走"+basket.sub());
Thread.sleep(r.nextInt(10)*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}
public class Test01 {
public static void main(String[] args) {
Basket b = new Basket();
Producer p1 = new Producer("p1", b);
Consumer c1 = new Consumer("c1", b);
Consumer c2 = new Consumer("c2", b);
ExecutorService es = Executors.newCachedThreadPool();
es.execute(p1);
es.execute(c1);
es.execute(c2);
}
}


View Code
效果

消费者:c1尝试取走,已取完。。等待生产
消费者:c2尝试取走,已取完。。等待生产
生产者:p1,尝试生产。。成功生产苹果0
消费者:c2尝试取走,成功取走苹果0
生产者:p1,尝试生产。。成功生产苹果1
生产者:p1,尝试生产。。成功生产苹果2
消费者:c1尝试取走,成功取走苹果1
消费者:c2尝试取走,成功取走苹果2
生产者:p1,尝试生产。。成功生产苹果3
生产者:p1,尝试生产。。成功生产苹果4
消费者:c1尝试取走,成功取走苹果3
消费者:c1尝试取走,成功取走苹果4
消费者:c2尝试取走,已取完。。等待生产
消费者:c1尝试取走,已取完。。等待生产
生产者:p1,尝试生产。。成功生产苹果5
消费者:c1尝试取走,成功取走苹果5
消费者:c2尝试取走,已取完。。等待生产
生产者:p1,尝试生产。。成功生产苹果6
消费者:c2尝试取走,成功取走苹果6
生产者:p1,尝试生产。。成功生产苹果7
消费者:c2尝试取走,成功取走苹果7
消费者:c2尝试取走,已取完。。等待生产
生产者:p1,尝试生产。。成功生产苹果8
消费者:c2尝试取走,成功取走苹果8
生产者:p1,尝试生产。。成功生产苹果9
生产者:p1,尝试生产。。成功生产苹果10
消费者:c1尝试取走,成功取走苹果9
消费者:c2尝试取走,成功取走苹果10


add方法在添加元素的时候,若超出了度列的长度会直接抛出异常。

put方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。

offer方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false。

remove:若队列为空,抛出NoSuchElementException异常。

take:若队列为空,发生阻塞,等待有元素。

poll: 若队列为空,返回null。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: