BlockingQueue方法有四种形式,具有不同的操作方式,不能立即满足,但可能在将来的某个时间点满足:
一个抛出异常,
第二个返回一个特殊值(空了,继续取值,返回 null 或 满了,继续添加,返回false ;没满返回true,具体取决于操作),
第三个程序将无限期地阻止当前线程,直到操作成功为止,
第四个程序块在放弃之前只有给定的最大时限。
代码测试
public static void main(String[] args) throws InterruptedException {
test2();
}
// 1. 抛出异常 add || remove || 检测队首元素element
public static void test1() {
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
// 添加元素
blockingQueue.add("a");
blockingQueue.add("b");
blockingQueue.add("c");
// 继续添加,超出容量,报异常 -> java.lang.IllegalStateException
// blockingQueue.add("d");
// 取出元素
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// 继续取,此时没有元素,报异常 -> java.util.NoSuchElementException
// System.out.println(blockingQueue.remove());
}
// 2. 添加元素,返回true,满了,返回false
// 移除元素,若为空,则返回null
// offer || poll || 检测队首元素peek
public static void test2() {
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
// 添加元素,成功返回true
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
// 继续添加,超出容量,返回false
System.out.println(blockingQueue.offer("d"));
// 取出元素
System.out.println(blockingQueue.poll());
// 测试队头元素,取出一个,此时为b
System.out.println(blockingQueue.peek());
System.out.println(blockingQueue.poll());
// 测试队头元素,取出一个,此时为c
System.out.println(blockingQueue.element());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.peek());
// 继续取,此时没有元素,返回null
System.out.println(blockingQueue.poll());
}
// 3. 添加元素,满,则阻塞等待, 一直等待
// 移除元素,空,则阻塞等待, 一直等待
// put || take
public static void test3() throws InterruptedException {
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
// 添加元素
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// 继续添加,超出容量,阻塞
// blockingQueue.put("d");
// 取出元素
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
// 继续取,此时没有元素,阻塞
System.out.println(blockingQueue.take());
}
// 4. 添加元素,返回true,满了,超时等待
// 移除元素,若为空,超时等待
// offer || poll 此两个的重载方法
public static void test4() throws InterruptedException {
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(3);
// 添加元素,成功返回true
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
// 等待2s,返回false
System.out.println(blockingQueue.offer("d", 2, TimeUnit.SECONDS));
// 取出元素
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
// 继续取,此时没有元素,等待2s,返回null
System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
}
}
同步队列
同步队列没有任何内部容量,甚至没有一个容量。 你不能peek在同步队列,因为一个元素,当您尝试删除它才存在; 您无法插入元素(使用任何方法),除非另有线程正在尝试删除它; 你不能迭代,因为没有什么可以迭代。 队列的头部是第一个排队的插入线程尝试添加到队列中的元素; 如果没有这样排队的线程,那么没有元素可用于删除,并且poll()将返回null 。
演示
// 同步队列,等待取的时候,才往里面添加元素
public class SynchronousQueueTest {
public static void main(String[] args) {
// BlockingQueue是SynchronousQueue的父亲
BlockingQueue<String> blockingQueue = new SynchronousQueue<>();
// 开启线程,放入元素
new Thread(() -> {
try {
System.out.println("开始放入aaa");
// 执行到put方法时,只有当有其他线程尝试取出元素时,才会继续执行此方法
blockingQueue.put("aaa");
System.out.println("放入aaa完成");
System.out.println("开始放入bbb");
blockingQueue.put("bbb");
System.out.println("放入bbb完成");
System.out.println("开始放入ccc");
blockingQueue.put("ccc");
System.out.println("放入ccc完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 开启线程取出元素
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(15);
System.out.println("尝试取出");
String take = blockingQueue.take();
System.out.println("取出"+take+"完成");
TimeUnit.SECONDS.sleep(15);
System.out.println("尝试取出");
String take1 = blockingQueue.take();
System.out.println("取出"+take1+"完成");
TimeUnit.SECONDS.sleep(15);
System.out.println("尝试取出");
String take2 = blockingQueue.take();
System.out.println("取出"+take2+"完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}