阻塞队列BlockingQueue

BlockingQueue 使用(生产者-消费者)

java.util.concurrent包中的Java BlockingQueue接口表示一个线程安全的队列,可以放入并获取实例。
在这篇文章中,我会告诉你如何使用这个BlockingQueue。

本文将不讨论如何在Java中实现BlockingQueue。如果您对此感兴趣,在我的偏理论的Java并发教程中有一个关于阻塞队列的文章。

BlockingQueue 使用在这里插入图片描述

生产线程将持续生产新对象并将它们插入队列,直到队列达到它可以包含的上限。换句话说,这是极限。如果阻塞队列达到其上限,则会在尝试插入新对象时阻塞生产线程。在消耗线程将对象带出队列之前,它一直处于阻塞状态。

消费线程不断将对象从阻塞队列中取出,并对其进行处理。如果消费线程试图将对象从空队列中取出,则消费线程将被阻塞,直到生成的线程将对象放入队列。

BlockingQueue 方法

BlockingQueue有4种不同的方法来插入、删除和检查队列中的元素。每一组方法的行为都是不同的,以防被请求的操作不能立即执行。下面是这些方法的一个表:

Throws Exception特殊值阻塞超时
Insertadd(o)offer(o)put(o)offer(o, timeout, timeunit)
Removeremove(o)poll()take()poll(timeout, timeunit)
Examineelement()peek()

这四种不同的行为方式意思

  1. Throws Exception: 如果尝试的操作不可能立即发生,则抛出一个异常。
  2. 特殊值:如果尝试的操作不能立即执行,则会返回一个特殊值(通常为true / false)。
  3. 阻塞:如果尝试的操作不可能立即执行,那么该方法将阻塞。
  4. 超时:如果尝试的操作不可能立即执行,则该方法调用将阻塞,但不会超过给定的超时。
    返回一个特殊值,告诉操作是否成功(通常为true / false)。

无法将null插入到BlockingQueue中。如果尝试插入null,则BlockingQueue将引发NullPointerException。

也可以访问BlockingQueue中的所有元素,而不仅仅是开始和结束处的元素。例如,假设你需要处理队列中的一个对象,但你的应用程序决定不处理它。然后你可以调用remove(o)删除队列中的特定对象。但是,这并不是非常有效,所以除非你真的需要,否则不应该使用这些Collection方法

BlockingQueue 实现

由于BlockingQueue是一个接口,因此您需要使用它的一个实现来使用它。java.util.concurrent包具有以下BlockingQueue接口(在Java 6中)的实现:

BlockingQueue 例子

这是一个Java BlockingQueue示例。该示例使用BlockingQueue接口的ArrayBlockingQueue实现。

首先,BlockingQueueExample类在不同的线程中启动生产者和消费者。生产者将字符串插入共享BlockingQueue中,消费者将它们取出。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueExample {
    public static void main(String[] args) throws Exception {

        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);
    }
}

这是生产者类。
注意它在每个put()调用之间的使用sleep。这将导致消费者在等待队列中的对象时阻塞。

import java.util.concurrent.BlockingQueue;

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(1000);
            queue.put("2");
            Thread.sleep(1000);
            queue.put("3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这是消费者类。
它只是从队列中取出对象,并将它们打印到System.out。

import java.util.concurrent.BlockingQueue;

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());  //Producer存入就可以从队列取出来,如果producer
            System.out.println(queue.take());  //如果Producer的堵塞队列是空的,再取就造成阻塞
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值