java并发编程工具类JUC之ArrayBlockingQueue

作者:字母哥博客 时间:2023-07-04 21:02:20 

Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一个可以存取元素,并且线程安全的队列。换句话说,当多线程同时从 JavaBlockingQueue中插入元素、获取元素的时候,不会导致任何并发问题(元素 * 入多次、处理多次等问题)。

从java BlockingQueue可以引申出一个概念:阻塞队列,是指队列本身可以阻塞线程向队列里面插入元素,或者阻塞线程从队列里面获取元素。比如:当一个线程尝试去从一个空队列里面获取元素的时候,这个线程将被阻塞直到队列内元素数量不再为空。当然,线程是否会被阻塞取决于你调用什么方法从BlockingQueue获取元素,有的方法会阻塞线程,有的方法会抛出异常等等,下文我们会详细介绍。

ArrayBlockingQueueBlockingQueue接口的实现类,它是有界的阻塞队列,内部使用数组存储队列元素。这里的“有界”是指存储容量存在上限,不能无限存储元素。在同一时间内存储容量存在着一个上限值,这个上限制在初始实例化的时候指定,之后便不能修改了。

ArrayBlockingQueue内部采用FIFO (First In, First Out)先进先出的方法实现队列数据的存取,队首的元素是在队列中保存时间最长的元素对象,队尾的元素是在队列中保存时间最短的元素对象。

下面的代码说明如何初始化一个ArrayBlockingQueue,并向其中添加一个对象:


BlockingQueue queue = new ArrayBlockingQueue(1024);
queue.put("1");   //向队列中添加元素
Object object = queue.take();   //从队列中取出元素

BlockingQueue可以通过泛型来限定队列中存储数据的类型,下面的代码以String为泛型,表示该队列只能存储String类型。


BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1024);
queue.put("1");
String string = queue.take();

实现一个生产消费的实例

在前面的文章中我们曾经讲过:BlockingQueue经常被用于生产消费的缓冲队列。下面我们就使用ArrayBlockingQueue来真正的实现一个生产消费的例子。

BlockingQueueExample开启两个独立线程,一个是Producer生产者线程,负责向队列中添加数据;另一个是Consumer消费者线程,负责从队列中取出数据进行处理。


public class BlockingQueueExample {

public static void main(String[] args) throws Exception {
       //使用ArrayBlockingQueue初始化一个BlockingQueue,指定容量的上限为1024
       BlockingQueue queue = new ArrayBlockingQueue(1024);

Producer producer = new Producer(queue);  //生产者
       Consumer consumer = new Consumer(queue);  //消费者

new Thread(producer).start();  //开启生产者线程
       new Thread(consumer).start();  //开启消费者线程

Thread.sleep(4000);
   }
}

Producer为生产者,每隔10秒钟使用put()方法向队列中放入一个对象,放入三次。在这10秒的间隔内,队列数据被消费者取走之后将导致消费者线程阻塞。


public class Producer implements Runnable{

protected BlockingQueue queue = null;

public Producer(BlockingQueue queue) {
       this.queue = queue;
   }

public void run() {
       try {
           queue.put("1");
           Thread.sleep(10000);
           queue.put("2");
           Thread.sleep(10000);
           queue.put("3");
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}

下面的代码是消费者类Consumer,它从队列中获取待处理的元素对象,并调用System.out将其打印出来。


public class Consumer implements Runnable{

protected BlockingQueue queue = null;

public Consumer(BlockingQueue queue) {
       this.queue = queue;
   }

public void run() {
       try {
           System.out.println(queue.take());
           System.out.println(queue.take());
           System.out.println(queue.take());
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}

上面的代码打印结果是每隔10秒打印一次,因为其中take()方法在队列内没有元素可以取到的时候,会阻塞当前的消费者线程,让其处于等待状态,这个方法我们在上一节介绍BlockingQueue的时候就已经进行过说明。

来源:https://www.cnblogs.com/zimug/p/14831660.html

标签:java,ArrayBlockingQueue
0
投稿

猜你喜欢

  • Java运算符从见过到掌握下

    2023-01-29 15:47:19
  • Mybatis一对多查询的两种姿势(值得收藏)

    2023-07-01 00:20:08
  • Java开发之Lombok指南

    2022-11-19 21:49:28
  • Java数据结构之实现哈希表的分离链接法

    2023-09-06 04:50:17
  • Spring之WEB模块配置详解

    2023-12-05 13:21:48
  • 聊一聊jdk1.8中的ArrayList 底层数组是如何扩容的

    2023-11-16 08:55:50
  • Android实现摇一摇功能

    2023-07-23 20:21:11
  • Java SpringBoot实现AOP

    2023-05-31 05:49:30
  • C#操作JSON(序列化与反序列化)的方法详解

    2022-01-27 20:15:10
  • Android 实现定时器的四种方式总结及实现实例

    2023-04-20 15:22:04
  • c#装箱和拆箱知识整理

    2023-03-14 00:42:02
  • c#在excel中添加超链接示例分享

    2023-06-03 14:10:45
  • Java 用反射设置对象的属性值实例详解

    2023-11-26 03:56:51
  • 详解SpringBoot注册Windows服务和启动报错的原因

    2022-12-28 17:10:09
  • 2022最新Java泛型详解(360度无死角介绍)

    2022-03-08 15:13:42
  • C#绘制中国象棋棋盘

    2021-05-27 15:08:44
  • Commons beanutils组件简介

    2023-11-28 07:13:27
  • Java中统计字符个数以及反序非相同字符的方法详解

    2022-10-21 10:48:02
  • java实现简单猜拳小游戏

    2021-09-01 07:49:46
  • Java Lambda表达式与匿名内部类的联系和区别实例分析

    2022-01-05 21:10:22
  • asp之家 软件编程 m.aspxhome.com