阻塞队列
PPG007 ... 2021-12-28 About 2 min
# 阻塞队列
Tips
写入:如果队列满了,就必须阻塞等待。
取:如果队列为空,就必须阻塞等待生产。
阻塞队列使用场景:多线程并发、线程池。
# 阻塞队列的四组API
方式 | 抛出异常 | 有返回值,不抛出异常 | 阻塞、等待 | 超时等待 |
---|---|---|---|---|
添加 | add() | offer() | put() | offer(E e, long timeout, TimeUnit unit) |
移除 | remove() | poll() | take() | poll(long timeout, TimeUnit unit) |
获取队首元素 | element() | peek() | - | - |
抛出异常:
ArrayBlockingQueue<Object> objects = new ArrayBlockingQueue<>(5); for (int i = 0; i < 5; i++) { // 队列满会报异常 System.out.println(objects.add(i)); } System.out.println("========================="); for (int i = 0; i < 5; i++) { // 队列空会报异常 System.out.println(objects.remove()); } // 获取队首元素,队空则异常 System.out.println(objects.element());
1
2
3
4
5
6
7
8
9
10
11
12有返回值,不抛异常:
ArrayBlockingQueue<Object> objects = new ArrayBlockingQueue<>(5); for (int i = 0; i < 6; i++) { // 队满返回false System.out.println(objects.offer(i)); } System.out.println("========================="); for (int i = 0; i < 6; i++) { // 队空返回null System.out.println(objects.poll()); } // 队空返回null System.out.println(objects.peek());
1
2
3
4
5
6
7
8
9
10
11
12阻塞等待:
ArrayBlockingQueue<Object> objects = new ArrayBlockingQueue<>(5); for (int i = 0; i < 6; i++) { // 队满,则一直等待 objects.put(i); } System.out.println("========================="); for (int i = 0; i < 6; i++) { // 队空,则一直等待 System.out.println(objects.take()); }
1
2
3
4
5
6
7
8
9
10超时等待:
ArrayBlockingQueue<Object> objects = new ArrayBlockingQueue<>(5); for (int i = 0; i < 6; i++) { // 队满,则等待到指定时间后退出 System.out.println(objects.offer(i, 3, TimeUnit.SECONDS)); } System.out.println("========================="); for (int i = 0; i < 6; i++) { // 队空,则等待到指定时间后退出 System.out.println(objects.poll(3, TimeUnit.SECONDS)); }
1
2
3
4
5
6
7
8
9
10
# SynchronousQueue 同步队列
其中每个插入操作必须等待另一个线程相应的删除操作,反之亦然。 同步队列没有任何内部容量,甚至没有一个容量。
Tips
添加元素后,必须先取出才能继续添加。
仍然可以使用之前的 offer、poll 等方法,但是 offer 和 poll 只能实时。
public class SynchronousQueueDemo {
public static void main(String[] args) {
SynchronousQueue<String> strings = new SynchronousQueue<>(true);
new Thread(()->{
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"放入了第"+i+"个元素");
try {
strings.put(i + "");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程一").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获取了第"+i+"个元素");
try {
System.out.println(strings.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程二").start();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31