ArrayBlockingQueue阻塞队列

阻塞队列的关系图

在这里插入图片描述

ArrayBlockingQueue特点:FIFO(先进先出)

阻塞队列的概念:当队列值满后,队列处于等待状态

队列的概念:

写入:如果队列满了,就必须阻塞等待。
取出:如果队列值是空的,必须阻塞等待生产。

解决阻塞队列的四种方案

1.抛出异常

2.不抛异常处理

3.阻塞等待

4.超时等待

阻塞队列的add和poll方法使用
方式抛出异常有返回值,不抛异常阻塞等
添加addofferput
移除removepoll()take()
检测队列首次元素elemetpeek

1. 抛出异常: and 和 remove方法

队列未满时,正常情况下代码案例
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 队列的概念:
 * 写入:如果队列满了,就必须阻塞等待
 * 取出:如果队列值是空的,必须阻塞等待生产
 *学会使用对象的添加,取出方法
 *四种解决阻塞Api
 *	1.抛出异常
 *队列排列元素FIFO(先进先出)。 
 */
public class ArrayBlockingQueueTest {

	public static void main(String[] args) throws Exception {
		test1();
	}
	/**
	 * 1.抛出异常队列
	 * 描述:如果队列数量超出队列指定数量,添加和取出都出现异常
	 */
	public static void test1(){
		
		ArrayBlockingQueue queue = new ArrayBlockingQueue<>(4);
//		ArrayBlockingQueue queue = new ArrayBlockingQueue<>(4,true);
//		//加入队列
		System.out.println(queue.add("a"));
		System.out.println(queue.add("b"));
		System.out.println(queue.add("c"));
		System.out.println(queue.add("d"));
		System.out.println(queue.add("e"));//Queue full 抛出异常
//		//取出队列
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		
	}
}

输出结果:

true
true
true
true
a
b
c
d
阻塞队列已满时, 抛出异常 Queue full
public class ArrayBlockingQueueTest {

	public static void main(String[] args) throws Exception {
		test1();
	}
	/**
	 * 1.抛出异常队列
	 * 描述:如果队列数量超出队列指定数量,添加和取出都出现异常
	 */
	public static void test1(){
		// 4表示工作队列的长度
		ArrayBlockingQueue queue = new ArrayBlockingQueue<>(4);
		//加入队列
		System.out.println(queue.add("a"));
		System.out.println(queue.add("b"));
		System.out.println(queue.add("c"));
		System.out.println(queue.add("d"));
  	System.out.println(queue.add("e"));//Queue full 抛出异常
	 //取出队列
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		
	}
}

输出结果:

Exception in thread "main" true
true
true
true
java.lang.IllegalStateException: Queue full
	at java.util.AbstractQueue.add(AbstractQueue.java:98)
	at java.util.concurrent.ArrayBlockingQueue.add(ArrayBlockingQueue.java:312)
	at com.urun.example.myqueue.ArrayBlockingQueueTest.test1(ArrayBlockingQueueTest.java:53)
	at com.urun.example.myqueue.ArrayBlockingQueueTest.main(ArrayBlockingQueueTest.java:22)

2.阻塞队列已满时,不抛异常处理

public class ArrayBlockingQueueTest {

	public static void main(String[] args) throws Exception {
		test2();
	}
	/**
	 * 2.不抛出异常,
	 * 添加 :超出指定队列值返回:false
	 * 取出 :超出指定队列值返回:null
	 */
	public static void test2(){
		ArrayBlockingQueue queue = new ArrayBlockingQueue<>(4);
		//添加队列
		System.out.println(queue.offer("a"));
		System.out.println(queue.offer("b"));
		System.out.println(queue.offer("c"));
		System.out.println(queue.offer("d"));
		System.out.println(queue.offer("e"));//不抛出异常 ,返回false
		System.out.println("-----------------------");
		//取出队列
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll());//不抛出异常 ,返回null
	}
}

输出结果:

true
true
true
true
false
-----------------------
a
b
c
d
null

3.等待,阻塞 (一直等待)

public class ArrayBlockingQueueTest {

	public static void main(String[] args) throws Exception {
		test3();
	}
	/**
	 * 等待,阻塞 (一直等待)
	 * @throws InterruptedException 
	 * 添加 :未超出指定队列值时,正常执行,如果超出一直处于等待状态。
	 */
	public static void test3() throws InterruptedException{
		ArrayBlockingQueue queue = new ArrayBlockingQueue<>(4);
			queue.put("a");
			queue.put("b");
			queue.put("c");
			queue.put("d");
//			queue.put("e"); // 队列位置已满,一直阻塞
			System.out.println(queue.take());
			System.out.println(queue.take());
			System.out.println(queue.take());
			System.out.println(queue.take());
			System.out.println(queue.take());//没有这个元素
	}
}

输出结果:
在这里插入图片描述

4.等待,阻塞(等待超时)

public class ArrayBlockingQueueTest {

	public static void main(String[] args) throws Exception {
		test4();
	}
	/**
	 * 等待,阻塞(等待超时)
	 * 添加元素超过指定元素值时,等待3秒后执行后退,不会添加多余的元素
	 * 取出元素超过指定元素值时,等待3秒后执行后退,不会添加多余的元素
	 */
	public static void test4() throws InterruptedException{
		ArrayBlockingQueue queue = new ArrayBlockingQueue<>(4);
		//添加
		queue.offer("a");
		queue.offer("b");
		queue.offer("c");
		queue.offer("d");
		queue.offer("e",3 ,TimeUnit.SECONDS);//等待超过3秒就退出
		System.out.println(queue);
		//取出
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll(3,TimeUnit.SECONDS));//等待超过3秒就退出
	}
}

输出结果:

[a, b, c, d]
a
b
c
d
null

对比LinkedBlockingQueue和ArrayBlockingQueue区别

相同点:

1、LinkedBlockingQueue和ArrayBlockingQueue都实现了BlockingQueue接口;
2、LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的队列内部
3、都是使用ReentrantLock和Condition来保证生产和消费的同步;
4、当队列为空,消费者线程被阻塞;当队列装满,生产者线程被阻塞;
5、使用Condition的方法来同步和通信:await()和signal();

不同点:

1、LinkedBlockingQueue中的锁是分离的,生产者的锁PutLock,消费者的锁takeLock,而ArrayBlockingQueue生产者和消费者使用的是同一把锁;
2、他们的底层实现机制也不同LinkedBlockingQueue内部维护的是一个链表结构,在生产和消费的时候,需要创建Node对象进行插入或移除,大批量数据的系统中,其对于GC的压力会比较大而ArrayBlockingQueue内部维护了一个数组;
3、在生产和消费的时候,是直接将枚举对象插入或移除的,不会产生或销毁任何额外的对象实例
4、构造时候的区别LinkedBlockingQueue有默认的容量大小为:Integer.MAX_VALUE,当然也可以传入指定的容量大小
ArrayBlockingQueue在初始化的时候,必须传入一个容量大小的值,看其提供的构造方法就能知道
5、执行clear()方法
  LinkedBlockingQueue执行clear方法时,会加上两把锁
6、统计元素的个数
  LinkedBlockingQueue中使用了一个AtomicInteger对象来统计元素的个数,ArrayBlockingQueue则使用int类型来统计元素

视频解说

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唂雨云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值