Java 阻塞队列



阻塞队列(BlockingQueue)
栈和队列是在程序设计中被广泛使用的两种线性数据结构
Java5提供了阻塞队列的接口BlockingQueue,阻塞队列的概念是,一个指定长度的队列,如果队列满了,添加新元素的操作会被阻塞等待,直到有空位为止。同样,当队列为空时候,请求队列元素的操作同样会阻塞等待,直到有可用元素为止。
Java阻塞队列应用于生产者消费者模式、消息传递、并行任务执行和相关并发设计的大多数常见使用上下文。
程序的两个线程通过交替向BlockingQueue 中放入元素、取出元素,即可很好地控制线程的通信。
BlockingQueue 提供了两个支持阻塞的方法:
1)put(E e)
尝试把E元素放入BlockingQueue 中,如果该队列的元素已满,则阻塞该线程。
2)take()
尝试从BlockingQueue 的头部取出元素,如果该队列的元素已空,则阻塞该线程。
BlockingQueue定义的常用方法如下:
1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则招聘异常
2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false。
3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.
4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null
5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止
BlockingQueue 包含的方法之间的对应关系
BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类
1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.
2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的
3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.
4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。
package com.hainiu.list;

import java.util.concurrent.ArrayBlockingQueue;

import com.hainiu.thread.Call;
/**
    阻塞队列实现生产消费模式
*/
public class Test {
	public static void main(String[] args) {
		ArrayBlockingQueue<Call> abk = new ArrayBlockingQueue<>(3);
		Test test = new Test();
		Runnable sc = test.new SC(abk);
		new Thread(sc,"生产者1号").start();
		new Thread(sc,"生产者2号").start();
		new Thread(sc,"生产者3号").start();
		Runnable xf =test.new XF(abk);
		new Thread(xf,"	xiaofeizhe 	1号##").start();
		new Thread(xf,"	xiaofeizhe 	2号##").start();
		new Thread(xf,"	xiaofeizhe	3号##").start();
	}

	/**
	 * 生产线程
	 */
	class SC implements Runnable {
		int i = 1;
		ArrayBlockingQueue<Call> abk;
		public SC() {
			// TODO Auto-generated constructor stub
		}
		public SC( ArrayBlockingQueue<Call> abk) {
			super();
			this.abk = abk;
		}
		@Override
		public void run() {
			Call call = null;
			String name = null;
			String x = null;
			while(true){
				if( i %2 == 0){
					name = "华为";
					x = "荣耀";
				}else{
					name = "apple";
					x = " XXXXXX ";
				}
				synchronized (this) {
					// 创建一个手机对象
					call = new Call(name , x , i);
	
					i++;
				}
				try {
					// 该方法为 阻塞方法      如果队里满了 那么会自动阻塞
					abk.put(call);
					//System.out.println(Thread.currentThread().getName()+" 成功的放入货架一个产品   信息为 : "+call);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}

	}

	/**
	 * 消费线程
	 */
	class XF implements Runnable {
		ArrayBlockingQueue<Call> abk;
		public XF() {
			// TODO Auto-generated constructor stub
		}
		public XF( ArrayBlockingQueue<Call> abk) {
			super();
			this.abk = abk;
		}

		@Override
		public void run() {
			while(true){
				try {
					// 拿取一个   如果没有数据那么久阻塞
					Call call = abk.take();
					System.out.println(Thread.currentThread().getName()+"  成功卖出一个产品   "+call);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

阻塞队列(BlockingQueue)
栈和队列是在程序设计中被广泛使用的两种线性数据结构
Java5提供了阻塞队列的接口BlockingQueue,阻塞队列的概念是,一个指定长度的队列,如果队列满了,添加新元素的操作会被阻塞等待,直到有空位为止。同样,当队列为空时候,请求队列元素的操作同样会阻塞等待,直到有可用元素为止。
Java阻塞队列应用于生产者消费者模式、消息传递、并行任务执行和相关并发设计的大多数常见使用上下文。
程序的两个线程通过交替向BlockingQueue 中放入元素、取出元素,即可很好地控制线程的通信。
BlockingQueue 提供了两个支持阻塞的方法:
1)put(E e)
尝试把E元素放入BlockingQueue 中,如果该队列的元素已满,则阻塞该线程。
2)take()
尝试从BlockingQueue 的头部取出元素,如果该队列的元素已空,则阻塞该线程。
BlockingQueue定义的常用方法如下:
1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则招聘异常
2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false。
3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.
4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null
5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止
BlockingQueue 包含的方法之间的对应关系
BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类
1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.
2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的
3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.
4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。
### Java BlockingQueue 的使用方法及示例 #### 什么是BlockingQueue? `BlockingQueue` 是 Java 并发包 `java.util.concurrent` 中的一个接口,它代表了一个线程安全的队列。通过该接口,多个线程可以在不影响数据一致性的前提下向队列中插入或移除元素[^2]。 当一个线程尝试从空的 `BlockingQueue` 获取元素时,或者另一个线程尝试向已满的 `BlockingQueue` 插入元素时,这些操作可能会阻塞当前线程,直到条件满足为止[^1]。 --- #### 常见的BlockingQueue实现类 以下是几种常见的 `BlockingQueue` 实现类及其特点: - **ArrayBlockingQueue**: 由数组支持的有界阻塞队列,按 FIFO(先进先出)顺序存储数据。 - **LinkedBlockingQueue**: 可选容量上限的基于链表结构的无界阻塞队列,默认情况下大小无限大。 - **PriorityBlockingQueue**: 支持优先级排序的无界阻塞队列。 - **SynchronousQueue**: 不存储任何元素的特殊阻塞队列,每一个插入操作都必须等待另一个线程的对应移除操作[^3]。 --- #### 方法分类 `BlockingQueue` 提供了几种不同行为的方法来处理可能发生的异常情况: | 方法名 | 抛出异常 | 返回特定值 | 超时返回布尔值 | 阻塞直至成功 | |--------------|------------------|----------------|--------------------|-------------------| | add(e) | yes | no | no | no | | offer(e) | no | yes | no | no | | put(e) | no | no | no | yes | | poll(time) | no | yes | yes | no | | take() | no | no | no | yes | 上述表格展示了每种方法的行为差异,开发者可以根据具体需求选择合适的方式[^4]。 --- #### 示例代码 下面是一个简单的生产者-消费者模式的例子,展示如何利用 `BlockingQueue` 来同步两个线程之间的通信。 ```java import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ProducerConsumerExample { public static void main(String[] args) throws InterruptedException { // 创建一个容量为10的阻塞队列 BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10); Thread producerThread = new Thread(() -> { try { int value = 0; while (true) { System.out.println("Producing: " + value); queue.put(value++); // 如果队列满了,则此操作会阻塞 Thread.sleep(1000); // 模拟生产时间 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); Thread consumerThread = new Thread(() -> { try { while (true) { Integer consumedValue = queue.take(); // 如果队列为空,则此操作会阻塞 System.out.println("Consumed: " + consumedValue); Thread.sleep(2000); // 模拟消费时间 } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); producerThread.start(); consumerThread.start(); // 让主线程运行一段时间后再中断子线程 Thread.sleep(10000); producerThread.interrupt(); consumerThread.interrupt(); } } ``` 在这个例子中: - 生产者线程不断生成整数并将其加入到队列中; - 消费者线程则不断地从队列中取出整数进行处理; - 当队列达到其最大容量时,`put()` 方法会使生产者线程暂停执行;同样地,当队列为空时,`take()` 方法会让消费者线程进入等待状态[^5]。 --- #### 总结 `BlockingQueue` 是一种非常强大的工具,在多线程环境下尤其有用。它可以有效简化诸如生产者-消费者模型之类的复杂场景中的编程工作量,并提供多种灵活的操作方式以适应不同的业务逻辑需求。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值