并发队列之:BlockingQueue和ConcurrentLinkedQueue
一.并行和并发区别:
并行:是指两者同时执行一件事。比如赛跑,两个人都在不停的往前跑;
并发:是指资源有限的情况下,两者交替轮流使用资源。比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率。
二.什么叫线程安全
线程安全就是说多线程访问同一代码,不会产生不确定的结果。
反之线程不安全就是,多线程在访问同一代码时,会发生不确定因素,例如死锁,数据不一致性等。
三.LinkedBlockingQueue
LinkedBlockingQueue是一个线程安全的阻塞队列,它实现了BlockingQueue接口,BlockingQueue接口继承自java.util.Queue接口,并在这个接口的基础上增加了take和put方法,这两个方法正是队列操作的阻塞版本。
由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选;LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE;其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。
示例代码:
package com.lky.test; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.junit.Test; /**
* @Title: testBlockQueue.java
* @Package com.lky.test
* @Description:多线程模拟实现生产者消费者模型(阻塞队列)
* @author lky
* @date 2015年10月24日 下午5:08:01
* @version V1.0
*/
public class testBlockQueue { private Log log = LogFactory.getLog(testBlockQueue.class); /**
* @Title: testBlockQueue.java
* @Package com.lky.test
* @Description: 定义阻塞队列
* @author lky
* @date 2015年10月24日 下午5:07:28
* @version V1.0
*/
public class Basket {
// 队列的最大容量为3
BlockingQueue<String> basket = new LinkedBlockingQueue<String>(3); // 如果队列不满,则放入,否则阻塞等待
public void produce(String apple) throws InterruptedException {
basket.put(apple);
} // 如果队列不为空,则取出,否则阻塞等待
public String consumer() throws InterruptedException {
return basket.take();
}
} /**
* @Title: testBlockQueue.java
* @Package com.lky.test
* @Description: 定义生产者
* @author lky
* @date 2015年10月24日 下午5:18:17
* @version V1.0
*/
public class Produce implements Runnable {
private Basket basket;
private String fruit; public Produce(String fruit, Basket basket) {
this.basket = basket;
this.fruit = fruit;
} @Override
public void run() {
try {
while (true) {
log.info("[" + Thread.currentThread().getName() + "]" + "开始生产apple----->" + this.fruit);
basket.produce(fruit);
log.info("apple生产完毕!!!!");
Thread.sleep(1000);
}
} catch (Exception e) {
log.error("生产苹果异常!!!!!");
}
}
} /**
* @Title: testBlockQueue.java
* @Package com.lky.test
* @Description: 定义消费者
* @author lky
* @date 2015年10月24日 下午5:24:31
* @version V1.0
*/
public class Consumer implements Runnable {
private Basket basket; public Consumer(Basket basket) {
this.basket = basket;
} @Override
public void run() {
try {
while (true) {
String fruit = basket.consumer();
log.info("[" + Thread.currentThread().getName() + "]" + "取到一个水果: " + fruit);
Thread.sleep(1000);
} } catch (Exception e) {
log.error("消费者取苹果异常!!!!");
}
}
} @Test
public void test() {
System.out.println(Runtime.getRuntime().availableProcessors());//获取当前系统的cpu数目 Basket basket = new Basket();
Produce produce1 = new Produce("apple", basket);
Produce produce2 = new Produce("banna", basket);
Consumer consumer = new Consumer(basket); // 新建一个线程池
ExecutorService service = Executors.newCachedThreadPool(); service.submit(produce1);
service.submit(produce2);
service.submit(consumer); try {
Thread.sleep(20000);
} catch (Exception e) {
log.error("程序异常错误!!!!");
}
service.shutdown();
}
}
四 .ConcurrentLinkedQueue
ConcurrentLinkedQueue是Queue的一个安全实现.Queue中元素按FIFO原则进行排序.采用CAS操作,来保证元素的一致性。
示例代码:
package com.lky.test; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; /**
* @Title: testNBlockQueue.java
* @Package com.lky.test
* @Description: 多线程模拟实现生产者消费者模型(非阻塞式队列)
* @author lky
* @date 2015年10月24日 下午8:02:14
* @version V1.0
*/
public class testNBlockQueue {
private static Log log = LogFactory.getLog(testNBlockQueue.class);
private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>(); private static int count = 2;
private static CountDownLatch latch = new CountDownLatch(count); private static class Poll implements Runnable {
@Override
public void run() {
while (!queue.isEmpty()) {
log.info(Thread.currentThread().getName() + "消费一个商品: " + queue.poll());
}
latch.countDown();
}
} public static void main(String args[]) throws InterruptedException {
long timeStart = System.currentTimeMillis();
ExecutorService eService = Executors.newFixedThreadPool(4); // 生产商品
for (int i = 0; i < 100000; ++i) {
queue.offer(i);
} // 消费者
for (int i = 0; i < count; ++i) {
eService.submit(new Poll());
} latch.await();// 使得主线程阻塞,直到latch.getCount()为0
System.out.println("Cost time: " + (System.currentTimeMillis() - timeStart));
eService.shutdown();
}
}
总结:在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出)。Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。
并发队列之:BlockingQueue和ConcurrentLinkedQueue的更多相关文章
- 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理
· 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...
- 并发队列 ConcurrentLinkedQueue 及 BlockingQueue 接口实现的四种队列
队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有元素时,称为空队列. 在队列这 ...
- 阻塞队列LinkedBlockingQueue和并发队列ConcurrentLinkedQueue
LinkedBlockingQueue: public class LinkedBlockingQueue<E> extends AbstractQueue<E> implem ...
- 并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别和使用场景总结
三者区别与联系: 联系,三者 都是线程安全的.区别,就是 并发 和 阻塞,前者为并发队列,因为采用cas算法,所以能够高并发的处理:后2者采用锁机制,所以是阻塞的.注意点就是前者由于采用cas算 ...
- 自己总结 :并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别 和 使用场景总结
并发队列ConcurrentLinkedQueue.阻塞队列AraayBlockingQueue.阻塞队列LinkedBlockingQueue 区别 和 使用场景总结 分类: Java2013-0 ...
- Java并发包源码学习系列:基于CAS非阻塞并发队列ConcurrentLinkedQueue源码解析
目录 非阻塞并发队列ConcurrentLinkedQueue概述 结构组成 基本不变式 head的不变式与可变式 tail的不变式与可变式 offer操作 源码解析 图解offer操作 JDK1.6 ...
- 深入理解java:2.3.4. 并发编程concurrent包 之容器ConcurrentLinkedQueue(非阻塞的并发队列---循环CAS)
1. 引言 在并发编程中我们有时候需要使用线程安全的队列. 如果我们要实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法. 使用阻塞算法的队列可以用一个锁(入队和出 ...
- 解读 java 并发队列 BlockingQueue
点击添加图片描述(最多60个字)编辑 今天呢!灯塔君跟大家讲: 解读 java 并发队列 BlockingQueue 最近得空,想写篇文章好好说说 java 线程池问题,我相信很多人都一知半解的,包括 ...
- JAVA并发(4)-并发队列ConcurrentLinkedQueue
本文开始介绍并发队列,为后面介绍线程池打下基础.并发队列莫非也是出队.入队操作,还有一个比较重要的点就是如何保证其线程安全性,有些并发队列保证线程安全是通过lock,有些是通过CAS. 我们从Conc ...
- 并发队列ConcurrentLinkedQueue与LinkedBlockingQueue源码分析与对比
目录 前言 ConcurrentLinkedQueue 使用方法 存储结构 初始化 入队 出队 获取容器元素数量 LinkedBlockingQueue 使用方法 存储结构 初始化 入队 出队 获取容 ...
随机推荐
- Ubuntu12.04下使用valgrind内存测试工具测试Qt程序
1. 到官网http://valgrind.org/downloads/上下载valgrind最新版本: 2. 解压源码,执行./configure;make;make install后,默认安装到/ ...
- 超好用文件对比工具 – Beyond Compare
超好用文件对比工具 – Beyond Compare,开发中文件.目录对比神器,有了它,再也不用为找不到修改的内容而发愁了. 具备的丰富实用功能: 并列比较文件夹.FTP 网站或 Zip 文件: 为以 ...
- Java基础知识强化23:Java中数据类型转换(面试题)
1. 以下代码输出结果是( D ). public class Test { ...
- yii图片上传
http://wuhai.blog.51cto.com/2023916/953300 首先感谢这里的博主,提供了思路,不过在调用 $model->b_image->extensionNam ...
- mongodb查询只显示指定字段
db.COMMODITY_COMMODITY.find( { "areaCode" : "320100" , "backCatalogId" ...
- php和java静态变量用途的思考
静态变量有哪些用途? 比如创建单例对象. 统计访问次数.数量等等. 多线路和进程中可能会使用. 深入理解补充.... PHP 单例模式解析和实战 php设计模式——单例模式 php static 与 ...
- ORA-00214: controlfile '/u01/app/oracle/oradata/[sid]/control01.ctl' version inconsistent with file '/u01/app/oracle/oradata/[sid]/control03.ctl'
Sample error: SQL> startupORACLE instance started. Total System Global Area 285212672 bytesFixed ...
- 学习笔记之AJAX无刷新分页
利用AJAX实现无刷新分页技术原理: 其主要是利用AJAX的异步处理机制,实现数据的异步传递,它隐藏了客户端向服务端请求数据的状态,在客户端表现为无刷新的显示状态. 实现分页的步骤: 1.客服端点击页 ...
- 转载:svn clean up 失败解决方法
转载网址:http://www.tuicool.com/articles/biy6na 今天svn遇到一个头疼的问题,最开始更新的时候失败了,因为有文件被锁住了.按照以往的操作,我对父目录进行clea ...
- (function(){})(jQuery)的功能和用途?
1.为什么开发插件都这么写? 2.为什么要穿jQuery进去?在方法中直接用jquery的方法什么的不行吗? 1 首先(function(){})()这种写法 是创建了一个匿名的方法并立即执行(fun ...