1.阻塞队列
队列是一个数据结构,阻塞队列就是线程从一端添加数据,从一端拿取数据。当阻塞队列时空时,从队列中获取元素的操作将会被阻塞;当阻塞队列是满时,往队列里添加元素的操作将会被阻塞。
为什么需要阻塞队列?
线程之间的通信一般使用的是Object的wait()和notify(),阻塞队列不需要自己去关心什么时候线程被唤醒,什么时候线程阻塞,因为BlockingQueue自己会处理。
BlockingQueue接口
阻塞队列 | 描述 |
---|---|
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
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
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元素,队列会一致阻塞消费者线程直到队列可用
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.当阻塞队列满时,队列会阻塞生产社线程一定时间,超时后生产者线程会退出
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操作,都则不能继续添加元素。