reference : http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html

在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出)。Java提供的线程安全的Queue可以分为阻 塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际 应用中要根据实际需要选用阻塞队列或者非阻塞队列。

注:什么叫线程安全?这个首先要明确。线程安全就是说多线程访问同一代码,不会产生不确定的结果。

并行和并发区别

1、并行是指两者同时执行一件事,比如赛跑,两个人都在不停的往前跑;
2、并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率

LinkedBlockingQueue
由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选,LinkedBlockingQueue

可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候
会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。

package cn.thread;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; /**
* 多线程模拟实现生产者/消费者模型
*
* @author 林计钦
* @version 1.0 2013-7-25 下午05:23:11
*/
public class BlockingQueueTest2 {
/**
*
* 定义装苹果的篮子
*
*/
public class Basket {
// 篮子,能够容纳3个苹果
BlockingQueue<String> basket = new LinkedBlockingQueue<String>(3); // 生产苹果,放入篮子
public void produce() throws InterruptedException {
// put方法放入一个苹果,若basket满了,等到basket有位置
basket.put("An apple");
} // 消费苹果,从篮子中取走
public String consume() throws InterruptedException {
// take方法取出一个苹果,若basket为空,等到basket有苹果为止(获取并移除此队列的头部)
return basket.take();
}
} // 定义苹果生产者
class Producer implements Runnable {
private String instance;
private Basket basket; public Producer(String instance, Basket basket) {
this.instance = instance;
this.basket = basket;
} public void run() {
try {
while (true) {
// 生产苹果
System.out.println("生产者准备生产苹果:" + instance);
basket.produce();
System.out.println("!生产者生产苹果完毕:" + instance);
// 休眠300ms
Thread.sleep(300);
}
} catch (InterruptedException ex) {
System.out.println("Producer Interrupted");
}
}
} // 定义苹果消费者
class Consumer implements Runnable {
private String instance;
private Basket basket; public Consumer(String instance, Basket basket) {
this.instance = instance;
this.basket = basket;
} public void run() {
try {
while (true) {
// 消费苹果
System.out.println("消费者准备消费苹果:" + instance);
System.out.println(basket.consume());
System.out.println("!消费者消费苹果完毕:" + instance);
// 休眠1000ms
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
System.out.println("Consumer Interrupted");
}
}
} public static void main(String[] args) {
BlockingQueueTest2 test = new BlockingQueueTest2(); // 建立一个装苹果的篮子
Basket basket = test.new Basket(); ExecutorService service = Executors.newCachedThreadPool();
Producer producer = test.new Producer("生产者001", basket);
Producer producer2 = test.new Producer("生产者002", basket);
Consumer consumer = test.new Consumer("消费者001", basket);
service.submit(producer);
service.submit(producer2);
service.submit(consumer);
// 程序运行5s后,所有任务停止
// try {
// Thread.sleep(1000 * 5);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// service.shutdownNow();
} }

ConcurrentLinkedQueue
ConcurrentLinkedQueue是Queue的一个安全实现.Queue中元素按FIFO原则进行排序.采用CAS操作,来保证元素的一致性。
LinkedBlockingQueue
是一个线程安全的阻塞队列,它实现了BlockingQueue接口,BlockingQueue接口继承自java.util.Queue接口,并在这
个接口的基础上增加了take和put方法,这两个方法正是队列操作的阻塞版本。

package cn.thread;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ConcurrentLinkedQueueTest {
private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
private static int count = 2; // 线程个数
//CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
private static CountDownLatch latch = new CountDownLatch(count); public static void main(String[] args) throws InterruptedException {
long timeStart = System.currentTimeMillis();
ExecutorService es = Executors.newFixedThreadPool(4);
ConcurrentLinkedQueueTest.offer();
for (int i = 0; i < count; i++) {
es.submit(new Poll());
}
latch.await(); //使得主线程(main)阻塞直到latch.countDown()为零才继续执行
System.out.println("cost time " + (System.currentTimeMillis() - timeStart) + "ms");
es.shutdown();
} /**
* 生产
*/
public static void offer() {
for (int i = 0; i < 100000; i++) {
queue.offer(i);
}
} /**
* 消费
*
* @author 林计钦
* @version 1.0 2013-7-25 下午05:32:56
*/
static class Poll implements Runnable {
public void run() {
// while (queue.size()>0) {
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
latch.countDown();
}
}
} 复制代码

运行结果:
costtime 2360ms

改用while (queue.size()>0)后
运行结果:
cost time 46422ms

结果居然相差那么大,看了下ConcurrentLinkedQueue的API原来.size()是要遍历一遍集合的,难怪那么慢,所以尽量要避免用size而改用isEmpty().

总结了下, 在单位缺乏性能测试下,对自己的编程要求更加要严格,特别是在生产环境下更是要小心谨慎。

[Java 基础] 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法的更多相关文章

  1. 自己总结 :并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别 和 使用场景总结

    并发队列ConcurrentLinkedQueue.阻塞队列AraayBlockingQueue.阻塞队列LinkedBlockingQueue 区别 和  使用场景总结 分类: Java2013-0 ...

  2. 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法

    在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出).Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQ ...

  3. 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法(转)

    在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出).Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQ ...

  4. 并发队列ConcurrentLinkedQueue 和 阻塞队列LinkedBlockingQueue用法

    在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出).Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQ ...

  5. 并发队列ConcurrentLinkedQueue与阻塞队列LinkedBlockingQueue的区别

    1.  介绍背景 在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列. Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是Block ...

  6. 并发队列ConcurrentLinkedQueue、阻塞队列AraayBlockingQueue、阻塞队列LinkedBlockingQueue 区别和使用场景总结

      三者区别与联系: 联系,三者 都是线程安全的.区别,就是 并发  和 阻塞,前者为并发队列,因为采用cas算法,所以能够高并发的处理:后2者采用锁机制,所以是阻塞的.注意点就是前者由于采用cas算 ...

  7. 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理

    · 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...

  8. 25、Java并发性和多线程-阻塞队列

    以下内容转自http://ifeve.com/blocking-queues/: 阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操 ...

  9. java队列Queue及阻塞队列

    java队列 接口Queue类在java.util包,定义了以下6个方法 详细查看官方文档https://docs.oracle.com/javase/7/docs/api/java/util/Que ...

随机推荐

  1. window 常用软件

    参考链接: http://www.aiweibang.com/yuedu/721140.html http://www.aiweibang.com/yuedu/145263218.html 1.wox ...

  2. BZOJ2051——A Problem For Fun

    0.题意:给出一个N个结点的树,每条边有一个正整数权值,定义两个结点的距离为连接这两个结点路径上边权的和.对于每个结点i,它到其他N-1个结点都有一个距离,将这些距离从小到大排序,输出第K个距离. 1 ...

  3. polymorphic-associations 多态关联实例 ruby on rails

    这次做新项目的时候,把图片都放在了一个表里,其他表中不再存图片信息,通过多态关联建立表之间的关系. (1)新建picture表, component表不需要处理 class CreatePicture ...

  4. 【转】Oracle当中扫描数据的方法

    本文将对oracle当中扫描数据的存取方法进行介绍. 1) 全表扫描(Full Table Scans, FTS) 为实现全表扫描,Oracle读取表中所有的行,并检查每一行是否满足语句的WHERE限 ...

  5. 【架构】How To Use HAProxy to Set Up MySQL Load Balancing

    How To Use HAProxy to Set Up MySQL Load Balancing Dec  2, 2013 MySQL, Scaling, Server Optimization U ...

  6. python: extend (扩展) 与 append (追加) 的差别

    >>> li = ['a', 'b', 'c'] >>> li.extend(['d', 'e', 'f']) >>> li ['a', 'b', ...

  7. centos7下搭建git和gitlab版本库

    系统:centos7 安装依赖: yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-d ...

  8. (转)Xcode调试技巧

    转自http://www.apkbus.com/android-140340-1-1.html 这篇文章给大家带来的是一些Xcode实用技巧,比如: • 摆脱NSlog打印输出,使用断点日志. • 摆 ...

  9. javascript 导出Excel

    测试兼容IE google 火狐浏览器.看到的朋友也许你某一天也会需要. //obj是table表格外面嵌套div id function saveCode(obj) { try { var strH ...

  10. c++ 引用和指针

    1.引用 程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用.一旦初始化完成,引用将和它的初始值对象一直绑定在一起.因为无法令引用重新绑定到另外一个对象,因此引用必须初始化. int ival ...