BlockingQueue阻塞队列详解
BlockingQueue 和 SynchronousQueue
BlockingQueue
BlockingQueue的四组API:
① add 和 remove
add(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则抛出异常java.lang.IllegalStateException: Queue full
remove() :返回并删除队首元素,如果队列为空删除失败则抛出异常java.util.NoSuchElementException
element() :返回队首元素,队列为空则抛出异常java.util.NoSuchElementException
② offer 和 poll
offer(E e) :将指定的元素插入到此队列中,成功则返回true,队列满了插入失败则返回false
poll() :返回并删除队首元素,如果队列为空删除失败则返回null
peek() :返回队首元素,队列为空则返回null
③ put 和 take
put(E e) :将指定的元素插入到此队列中,没有返回值,如果队列满了则一直等待(阻塞),直到有元素从队列中被取出
take() :返回并删除队首元素,如果队列为空则一直等待(阻塞),直到有新的元素插入队列
④ offer(E e, long timeout, TimeUnit unit) 和 poll(long timeout, TimeUnit unit)
offer(E e, long timeout, TimeUnit unit) :将指定元素插入队列中,如果队列已满则等待给定时间,如果还是无法插入则返回false并执行下一条语句
poll(long timeout, TimeUnit unit) :返回并删除队首元素,如果队列为空则等待给定时间,如果队列还是为空无元素删除则返回null并执行下一条语句
public class BlockingQueueTest {
public static void main(String[] args) throws InterruptedException {
test4();
}
public static void test1(){
// 创建阻塞队列并设置容量大小
ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(arrayBlockingQueue.add("a")); // 将元素插入队列,插入成功返回true
System.out.println(arrayBlockingQueue.add("b"));
System.out.println(arrayBlockingQueue.add("c"));
//System.out.println(arrayBlockingQueue.add("d")); // 插入失败,超出队列容量抛出异常:java.lang.IllegalStateException: Queue full
System.out.println(arrayBlockingQueue.element()); // 返回队首元素,队列为空则抛出异常:java.util.NoSuchElementException
System.out.println(arrayBlockingQueue.remove()); // 返回并删除队首元素
System.out.println(arrayBlockingQueue.remove());
System.out.println(arrayBlockingQueue.remove());
//System.out.println(arrayBlockingQueue.remove()); // 删除失败,队列为空则抛出异常:java.util.NoSuchElementException
}
public static void test2(){
// 创建阻塞队列并设置容量大小
ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(arrayBlockingQueue.offer("a")); // 将元素插入队列,插入成功返回true
System.out.println(arrayBlockingQueue.offer("b"));
System.out.println(arrayBlockingQueue.offer("c"));
System.out.println(arrayBlockingQueue.offer("d")); // 插入失败,超出队列容量返回false
System.out.println(arrayBlockingQueue.peek()); // 返回队首元素,队列为空则返回null
System.out.println(arrayBlockingQueue.poll()); // 返回并删除队首元素
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll()); // 删除失败,队列为空返回null
}
public static void test3() throws InterruptedException {
// 创建阻塞队列并设置容量大小
ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
arrayBlockingQueue.put("a"); // 将指定的元素插入到此队列中,没有返回值
arrayBlockingQueue.put("b");
arrayBlockingQueue.put("c");
//arrayBlockingQueue.put("d"); // 队列满了则一直等待直到有元素从队列中取出
System.out.println(arrayBlockingQueue.take()); // 返回并删除队首元素
System.out.println(arrayBlockingQueue.take());
System.out.println(arrayBlockingQueue.take());
//System.out.println(arrayBlockingQueue.take()); // 如果队列为空则一直等待(阻塞),直到有新的元素插入队列
}
public static void test4() throws InterruptedException {
// 创建阻塞队列并设置容量大小
ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);
arrayBlockingQueue.offer("a");
arrayBlockingQueue.offer("b");
arrayBlockingQueue.offer("c");
System.out.println(arrayBlockingQueue.offer("d", 2, TimeUnit.SECONDS)); // 当队列满了,等待2秒还是插入不了则返回false并执行下一条语句
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll(2,TimeUnit.SECONDS)); // 当队列为空,等待2秒还是为空无元素删除则返回null并执行下一条语句
}
}
SynchronousQueue
SynchronousQueue同步队列是BlockingQueue的实现类
同步队列没有任何内部容量,甚至没有一个容量
SynchronousQueue同步队列其中每个插入操作必须等待另一个线程相应的删除操作,反之亦然
即插入一个元素必须等待删除取出一个元素后才能再插入一个元素,取出一个元素必须等待插入一个元素后才能取出
可以把SynchronousQueue同步队列想象成容量为1的一个阻塞队列BlockingQueue
public class SynchronousQueueTest {
public static void main(String[] args) {
SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"插入元素 a");
synchronousQueue.put("a");
System.out.println(Thread.currentThread().getName()+"插入元素 b");
synchronousQueue.put("b");
System.out.println(Thread.currentThread().getName()+"插入元素 c");
synchronousQueue.put("c");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try{
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"取出元素"+synchronousQueue.poll());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"B").start();
}
}
结果:
A插入元素 a
B取出元素a
A插入元素 b
B取出元素b
A插入元素 c
B取出元素c
由于队列没有容量,因此不能调用peek操作,因为只有移除元素时才有元素
本文地址:https://blog.csdn.net/weixin_43912697/article/details/114328321
上一篇: final关键字的几种用法