并发编程栏目代码 GitHub package 地址: 点击打开链接
博客并发编程栏目 : 点击打开链接
实现
LinkedBlockingQueue是一个基于已链接节点的、范围任意的blocking queue的实现。 阻塞队列
此队列按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。
新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,
但是在大多数并发应用程序中,其可预知的性能要低。
可选的容量范围构造方法参数作为防止队列过度扩展的一种方法。
如果未指定容量,则它等于 Integer.MAX_VALUE。除非插入节点会使队列超出容量,否则每次插入后会动态地创建链接节点。
- 如果未指定容量,默认容量为Integer.MAX_VALUE ,容量范围可以在构造方法参数中指定作为防止队列过度扩展。
- 此对象是 线程阻塞-安全的
- 不接受 null 元素
- 它实现了BlockingQueue接口。
- 实现了 Collection 和 Iterator 接口的所有可选 方法。
部分方法API
private static void linkedBlockingQueue2Void() {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
//将指定元素插入到此队列的尾部(如果立即可行且不会超出此队列的容量),在成功时返回 true,如果此队列已满,则返回 false。
boolean isOffer = queue.offer("aa");
queue.offer("ee");
try {
// 等待1s
isOffer = queue.offer("bb", 1000L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println("offer(E e, long timeout, TimeUnit unit) run ... 在等待时被中断...");
}
//获取但不移除此队列的头;如果此队列为空,则返回 null。
String head = queue.peek();
//获取并移除此队列的头,如果此队列为空,则返回 null。
head = queue.poll();
try {
//获取并移除此队列的头部,在指定的等待时间前等待可用的元素(如果有必要)。
head = queue.poll(1000L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println("poll(long timeout, TimeUnit unit) run ... 在等待时被中断...");
}
try {
//TODO 获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)。
queue.take();
} catch (InterruptedException e) {
System.out.println("take() run ... 在等待时被中断...");
}
try {
//将指定元素插入到此队列的尾部,如有必要,则等待空间变得可用。
queue.put("cc");
} catch (InterruptedException e) {
System.out.println("put(E e) run ... 在等待时被中断...");
}
//返回理想情况下(没有内存和资源约束)此队列可接受并且不会被阻塞的附加元素数量。
int remainingCapacity2Size = queue.remainingCapacity();
//移除元素,如果存在
queue.remove("dd");
}
鉴于此队列实现的生产者消费者模型
模拟对象
/**
* 模拟商品对象
*
* @author wei.Li by 14-8-21.
*/
public class CommodityObj {
private String objId;
public CommodityObj() {
this.objId = UUID.randomUUID().toString();
}
public String getObjId() {
return objId;
}
public void setObjId(String objId) {
this.objId = objId;
}
@Override
public String toString() {
return "Obj{" +
"objId='" + objId + '\'' +
'}';
}
}
生产者 消费者,可以认为 new 一个对象即为一个生产供应商 、消费商
/**
* 生产者
*
* @author wei.Li by 14-8-21.
*/
public class Producer implements Runnable {
@Override
public void run() {
while (MarketStorage.isRun_Cousumer) {
//随机睡眠
try {
Thread.sleep(new Random().nextInt(MarketStorage.PRODUCER_THREAD_SLEEP));
//生产对象
CommodityObj commodityObj = new CommodityObj();
MarketStorage.blockingQueue.put(commodityObj);
System.out.println(this + " producer obj succeed->" + commodityObj);
MarketStorage.getProducerObj_Count.getAndIncrement();//计数器++
System.out.println("getProducerObj_Count is :" + MarketStorage.getProducerObj_Count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
*
* @author wei.Li by 14-8-21.
*/
public class Consumer implements Runnable {
@Override
public void run() {
while (MarketStorage.isRun_Cousumer) {
try {
//随机睡眠
Thread.sleep(new Random().nextInt(MarketStorage.CONSUMER_THREAD_SLEEP));
//消费对象
CommodityObj commodityObj = MarketStorage.blockingQueue.take();
System.out.println(this + " consumer obj ->" + commodityObj);
MarketStorage.getConsumerObj_Count.getAndIncrement();//计数器++
System.out.println("getConsumerObj_Count is :" + MarketStorage.getConsumerObj_Count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
市场演示仓库 - 调度生产者消费者
/**
* 市场演示仓库
*
* @author wei.Li by 14-8-21.
*/
public class MarketStorage {
//生产者线程池
protected static final ExecutorService EXECUTOR_SERVICE_PRODUCER
= Executors.newFixedThreadPool(10);
//启动生产者线程数量
protected static final int PRODUCER_THREAD_NUM = 2;
//生产者线程睡眠随机最大时间
protected static final int PRODUCER_THREAD_SLEEP = 200;
//生产者生成对象次数
protected static AtomicInteger getProducerObj_Count = new AtomicInteger(0);
//是否生产
protected static boolean isRun_Producer = true;
//消费者线程池
protected static final ExecutorService EXECUTOR_SERVICE_CONSUMER
= Executors.newFixedThreadPool(10);
//启动消费者线程数量
protected static final int CONSUMER_THREAD_NUM = 20;
//消费者线程睡眠随机最大时间
protected static final int CONSUMER_THREAD_SLEEP = 1000;
//消费者消费对象次数
protected static AtomicInteger getConsumerObj_Count = new AtomicInteger(0);
//是否消费
protected static boolean isRun_Cousumer = true;
//市场仓库-存储数据的队列 默认仓库容量大小100
/**
* @see com.java.queue.LinkedBlockingQueue_#linkedBlockingQueue2Void()
*/
protected static LinkedBlockingQueue<CommodityObj> blockingQueue
= new LinkedBlockingQueue<CommodityObj>(100);
/**
* 生成生产者线程
*/
private static void runProducer() {
for (int i = 0; i < PRODUCER_THREAD_NUM; i++) {
EXECUTOR_SERVICE_PRODUCER.submit(new Producer());
}
}
/**
* 生成消费者线程生成
*/
private static void runConsumer() {
for (int i = 0; i < CONSUMER_THREAD_NUM; i++) {
Thread thread = new Thread(new Consumer());
EXECUTOR_SERVICE_CONSUMER.submit(thread);
}
}
/**
* 停止线程生产与消费
* 关闭线程池
*/
private static void shumdown() {
if (!EXECUTOR_SERVICE_PRODUCER.isShutdown()) {
isRun_Producer = false;
EXECUTOR_SERVICE_PRODUCER.shutdown();
}
if (!EXECUTOR_SERVICE_CONSUMER.isShutdown()) {
isRun_Cousumer = false;
EXECUTOR_SERVICE_CONSUMER.shutdown();
}
}
public static void main(String[] args) {
runConsumer();
runProducer();
/**
* 1 min 后停止执行
*/
new Timer().schedule(new TimerTask() {
@Override
public void run() {
shumdown();
System.out.println("~~~~~~~~~~~~ shumdown done ~~~~~~~~~~~~~~");
}
}, 1000 * 60L);
}
}
执行结果部分内容
...
...
...
com.java.queue.example.Producer@517f906c producer obj succeed->Obj{objId='1c80afd0-6d4d-4f6b-bd52-a1ed48d62136'}
producerObj_Count->109
com.java.queue.example.Consumer@352ebfc0 consumer obj ->Obj{objId='1c80afd0-6d4d-4f6b-bd52-a1ed48d62136'}
consumerObj_Count->109
com.java.queue.example.Consumer@2bcfaa37 consumer obj ->Obj{objId='fd6c17fb-cb78-4542-883d-0a87e12bb454'}
consumerObj_Count->110
com.java.queue.example.Producer@1ddc8d7a producer obj succeed->Obj{objId='fd6c17fb-cb78-4542-883d-0a87e12bb454'}
producerObj_Count->110
com.java.queue.example.Producer@517f906c producer obj succeed->Obj{objId='2e12de1e-648f-4edc-8620-9ad36313055e'}
producerObj_Count->111
com.java.queue.example.Consumer@271d296 consumer obj ->Obj{objId='2e12de1e-648f-4edc-8620-9ad36313055e'}
consumerObj_Count->111
~~~~~~~~~~~~ shumdown done ~~~~~~~~~~~~~~
com.java.queue.example.Producer@1ddc8d7a producer obj succeed->Obj{objId='5b91f0fa-a000-41cc-b74f-088fd6f04c01'}
producerObj_Count->112
com.java.queue.example.Consumer@3f32bcde consumer obj ->Obj{objId='5b91f0fa-a000-41cc-b74f-088fd6f04c01'}
consumerObj_Count->112
com.java.queue.example.Producer@517f906c producer obj succeed->Obj{objId='bebff1c2-8489-40bb-a742-04f56461b2d4'}
producerObj_Count->113
com.java.queue.example.Consumer@6ca1879 consumer obj ->Obj{objId='bebff1c2-8489-40bb-a742-04f56461b2d4'}
consumerObj_Count->113
producerObj_Count->109
com.java.queue.example.Consumer@352ebfc0 consumer obj ->Obj{objId='1c80afd0-6d4d-4f6b-bd52-a1ed48d62136'}
consumerObj_Count->109
com.java.queue.example.Consumer@2bcfaa37 consumer obj ->Obj{objId='fd6c17fb-cb78-4542-883d-0a87e12bb454'}
consumerObj_Count->110
com.java.queue.example.Producer@1ddc8d7a producer obj succeed->Obj{objId='fd6c17fb-cb78-4542-883d-0a87e12bb454'}
producerObj_Count->110
com.java.queue.example.Producer@517f906c producer obj succeed->Obj{objId='2e12de1e-648f-4edc-8620-9ad36313055e'}
producerObj_Count->111
com.java.queue.example.Consumer@271d296 consumer obj ->Obj{objId='2e12de1e-648f-4edc-8620-9ad36313055e'}
consumerObj_Count->111
~~~~~~~~~~~~ shumdown done ~~~~~~~~~~~~~~
com.java.queue.example.Producer@1ddc8d7a producer obj succeed->Obj{objId='5b91f0fa-a000-41cc-b74f-088fd6f04c01'}
producerObj_Count->112
com.java.queue.example.Consumer@3f32bcde consumer obj ->Obj{objId='5b91f0fa-a000-41cc-b74f-088fd6f04c01'}
consumerObj_Count->112
com.java.queue.example.Producer@517f906c producer obj succeed->Obj{objId='bebff1c2-8489-40bb-a742-04f56461b2d4'}
producerObj_Count->113
com.java.queue.example.Consumer@6ca1879 consumer obj ->Obj{objId='bebff1c2-8489-40bb-a742-04f56461b2d4'}
consumerObj_Count->113