BioBioBio

阻塞队列

字数统计: 1k阅读时长: 4 min
2020/10/01 Share

1.阻塞队列

队列是一个数据结构,阻塞队列就是线程从一端添加数据,从一端拿取数据。当阻塞队列时空时,从队列中获取元素的操作将会被阻塞;当阻塞队列是满时,往队列里添加元素的操作将会被阻塞

为什么需要阻塞队列?

线程之间的通信一般使用的是Object的wait()和notify(),阻塞队列不需要自己去关心什么时候线程被唤醒,什么时候线程阻塞,因为BlockingQueue自己会处理。

BlockingQueue接口

image-20201013153343662

阻塞队列 描述
ArrayBlickingQueue 数组结构组成的有界阻塞队列
LinkedBlockingQueue 链表结构组成的有界阻塞队列(默认大小Integer.MAX_VALUE,21亿)
PriorityBlockingQueue 支持优先级排序的无界阻塞队列
DelayQueue 使用优先级队列实现的延迟无界阻塞队列
SyncronousQueue 不存储元素的阻塞队列,即单个元素的队列
LinkedTransferQueue 链表结构组成的无界阻塞队列
LinkedBlockingDeque 链表结构组成的双向阻塞队列
API使用
方法类型 抛异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take() poll(time,unit)
检查 element() peek() 不可用 不可用
1.抛异常add和remove

1.异常:当阻塞队列满时,往队列中add元素会有IllegalStateException:Queue full;当阻塞队列为空时,再往队列remove元素就会有NoSuchElementException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("b"));
// blockingQueue.add("d"); //队列的大小为3,多余的会抛出异常

System.out.println(blockingQueue.element());//检查队列是否为空,返回队列首部

System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// blockingQueue.remove();//当队列为空时,再向队列中获取元素时会抛出异常
}
2.特殊值offer和poll

2.特殊值:插入方法,成功true失败返回false;移除方法成功返回队列的元素,失败返回null

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("d"));//当队列已经满后,添加失败,返回一个false
System.out.println(blockingQueue.element());//检查队列是否为空,返回队列首部
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());//当队列为空时,再向队列中获取元素时会返回一个null
}
3.使用put和take,会阻塞

3.一致阻塞:当阻塞队列满时,生产者继续put元素时,队列会阻塞生产者线程知道put数据成功或者中断退出;当阻塞队列为空时,消费者线程take元素,队列会一致阻塞消费者线程直到队列可用

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue(3);
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("b");
//blockingQueue.put("d");//超过3个会一致阻塞

System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//System.out.println(blockingQueue.take());//为空时,阻塞等待
}
4.超时退出使用加参数的offer和poll

4.当阻塞队列满时,队列会阻塞生产社线程一定时间,超时后生产者线程会退出

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue(3);
blockingQueue.offer("a",2L, TimeUnit.SECONDS);
blockingQueue.offer("b",2L, TimeUnit.SECONDS);
blockingQueue.offer("c",2L, TimeUnit.SECONDS);
blockingQueue.offer("d",2L, TimeUnit.SECONDS);//等待两秒,还没有空余位置,直接放弃

System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));
System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));//超过2S停止,过时不候
}
同步阻塞队列SynchronousQueue

SynchronousQueue没有容量,与其他的BlockingQueue不同,SynchronousQueue是一个不存储元素的BlockingQueue,每一个out操作必须等待一个take操作,都则不能继续添加元素。

CATALOG
  1. 1. 1.阻塞队列
    1. 1.1. BlockingQueue接口
    2. 1.2. API使用
    3. 1.3. 1.抛异常add和remove
    4. 1.4. 2.特殊值offer和poll
    5. 1.5. 3.使用put和take,会阻塞
    6. 1.6. 4.超时退出使用加参数的offer和poll
    7. 1.7. 同步阻塞队列SynchronousQueue