Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5304字,纯文字阅读大概需要8分钟。
内容图文
1.什么是阻塞队列?
所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了.
看一下线程的四种状态,首先是新创建一个线程,然后,通过start方法启动线程--->线程变为可运行可执行状态,然后通过数据产生共享,线程产生互斥---->线程状态变为阻塞状态---->阻塞状态想打开的话可以调用notify方法.
这里Java5中提供了封装好的类,可以直接调用然后构造阻塞状态,以保证数据的原子性.
2.如何实现?
主要是实现BlockingQueue接口.
比较常见的实现有:ArrayBlockingQueue,LinkedBlockingQueue,DelayedWorkQueue等竺
这里简单介绍ArrayBlockingQueue;
// 方式1 new ArrayBlockingQueue(int capacity);//Parameters:capacity the capacity of this queue //方式2public ArrayBlockingQueue(int capacity, boolean fair) ;//fair if true then queue accesses for threads blocked on insertion or removal, are processed in FIFO order; iffalse the access order is unspecified. //方式3public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) ;//c the collection of elements to initially contain
三种构造函数,比较常用的是1,2两种,2比1只是多了要不要排序,如果排序,那就是FIFO原则,即先进先出.
3.举例:
package com.amos.concurrent; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; /** * @ClassName: BlockingQueueTest * @Description: Java5新特性,阻塞队列 * @author : amosli * @email:hi_amos@outlook.com * @date Apr 27, 2014 10:01:51 PM */ public class BlockingQueueTest { public static void main(String[] args) { final BlockingQueue queue = new ArrayBlockingQueue(3); for(int i=0;i<2;i++){ new Thread(){ publicvoid run(){ while(true){ try { Thread.sleep((long)(Math.random()*1000)); System.out.println(Thread.currentThread().getName() + "准备放数据!"); queue.put(1); System.out.println(Thread.currentThread().getName() + "已经放了数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } new Thread(){ publicvoid run(){ while(true){ try { //将此处的睡眠时间分别改为100和1000,观察运行结果 Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "准备取数据!"); queue.take(); System.out.println(Thread.currentThread().getName() + "已经取走数据," + "队列目前有" + queue.size() + "个数据"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } }
效果如下图所示:
说明:这里新建一个队列后,主要调用的是put和take两种方法,一个是存,一个是取,这里由于将取的间隔时间设置的比较短,所以基本队列就没放满过.
4.改写之前的代码
方法1:Java核心知识点学习----多线程并发之线程间的通信,notify,wait
方法2:Java核心知识点学习----使用Condition控制线程通信
方法3:使用ArrayBlockingQueue
package com.amos.concurrent; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @ClassName: BlockingQueueCondition * @Description: 在前面用Condition实现的同步通知的例子的基础上,改为用阻塞队列来实现。 第一个线程:A.take()……..B.put() 第二个线程:B.take()……..A.put() * @author : amosli * @email:hi_amos@outlook.com * @date Apr 28, 2014 12:57:51 AM */ public class BlockingQueueCondition { public static void main(String[] args) { ExecutorService service = Executors.newSingleThreadExecutor(); final Business3 business = new Business3(); service.execute(new Runnable(){ publicvoid run() { for(int i=0;i<2;i++){ business.sub(); } } }); for(int i=0;i<3;i++){ business.main(); } } } class Business3{ BlockingQueue subQueue = new ArrayBlockingQueue(1); BlockingQueue mainQueue = new ArrayBlockingQueue(1); { try { mainQueue.put(1); } catch (InterruptedException e) { e.printStackTrace(); } } publicvoid sub(){ try { mainQueue.take(); for(int i=0;i<10;i++){ System.out.println(Thread.currentThread().getName() + " : " + i); } subQueue.put(1); }catch(Exception e){ } } publicvoid main(){ try { subQueue.take(); for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName() + " : " + i); } mainQueue.put(1); }catch(Exception e){ } } }
功能的实现都是完全一样的,不同的是,使用ArrayBlockingQueue会更简单.
5.官方---代码示例
典型的生产者消费者模型:
package com.amos.concurrent; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; /** * @ClassName: BlockingSample * @Description: 生产者消费者模型,阻塞,只有生产好了,才能去消费 * @author : amosli * @email:hi_amos@outlook.com * @date Apr 28, 2014 1:44:07 AM */ public class BlockingSample { public static void main(String[] args) { new BlockingSample().new Setup().main(); } class Producer implements Runnable { privatefinal BlockingQueue queue; Producer(BlockingQueue q) { queue = q; } publicvoid run() { try { while (true) { queue.put(produce()); System.out.println(Thread.currentThread().getName()+" 现在正在生产!"); } } catch (Exception ex) { ex.printStackTrace();} } String produce() { System.out.println("produce now ...."); return "produce"; } } class Consumer implements Runnable { privatefinal BlockingQueue queue; Consumer(BlockingQueue q) { queue = q; } publicvoid run() { try { while (true) { consume(queue.take()); System.out.println(Thread.currentThread().getName()+" 现在正在消费!"); } } catch (InterruptedException ex) { ex.printStackTrace();} } void consume(Object x) {System.out.println("consume...");} } class Setup { void main() { BlockingQueue q = new ArrayBlockingQueue<String>(1); Producer p = new Producer(q); Consumer c1 = new Consumer(q); Consumer c2 = new Consumer(q); new Thread(p).start(); new Thread(c1).start(); new Thread(c2).start(); } } }
效果如下图所示:
由图上可以看出,只有生产了才能消费,否则会形成阻塞.
原文:http://www.cnblogs.com/amosli/p/3695558.html
内容总结
以上是互联网集市为您收集整理的Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍全部内容,希望文章能够帮你解决Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。