一. 阻塞队列
1. 常见的阻塞队列:
ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,
此队列按FIFO原则对元素进行排序。
LinkedBlockingQueue:是一个基于链表结构的阻塞队列,
此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。
SynchronousQueue:是一个不存储元素的阻塞队列,
每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,
吞吐量通常要高于LinkedBlockingQueue。
2. ArrayBlockingQueue基础操作(API)
private static void Demo01() {
//阻塞队列,需要设置初始值
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//添加
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
/**
* 超出队列容量,在添加会报错。
* java.lang.IllegalStateException: Queue full
*/
//System.out.println(blockingQueue.add("x"));
//输出队头元素,可以判断这个队列是否为空。
System.out.println(blockingQueue.element());
//移出
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
/**
* 队列没有内容,在移出会报错。
* java.util.NoSuchElementException
*/
//System.out.println(blockingQueue.remove());
}
private static void Demo02() {
//阻塞队列,需要设置初始值
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//添加
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
//添加不进去,不报错返回 false
System.out.println(blockingQueue.offer("x"));
//检查队头元素
System.out.println(blockingQueue.peek());
//移出
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
//队列为空,输出时也不报错,输出 null。
System.out.println(blockingQueue.poll());
}
private static void Demo03() throws InterruptedException {
//阻塞队列,需要设置初始值
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//添加
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
//添加不进去,不报错,不返回,一直阻塞着,直到有地方为止。
//blockingQueue.put("x");
//取值
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//队列为空,输出时也不报错,也不输出null,在那阻塞着。
System.out.println(blockingQueue.take());
}
public static void main(String[] args) throws Exception {
//阻塞队列,需要设置初始值
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("b", 2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.offer("c", 2L, TimeUnit.SECONDS));
//阻塞 2秒后,输出 false
System.out.println(blockingQueue.offer("x", 2L, TimeUnit.SECONDS));
}
3. SynchronousQueue基础操作(API)
public static void main(String[] args) {
//不存储阻塞队列
BlockingQueue<String> blockingQueue = new SynchronousQueue<>();
//该线程负责加入数据
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "\t put 1");
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName() + "\t put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName() + "\t put 3");
blockingQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1").start();
//该线程负责移出数据
new Thread(() -> {
try {
//休眠 3秒,看一下效果。
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " " + blockingQueue.take());
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " " + blockingQueue.take());
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " " + blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2").start();
}
运行结果: