Queue一个先入先出(FIFO)的数据结构:
-
分为阻塞队列与非阻塞队:
阻塞队列与非阻塞队的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,比如从队列中移除一个或者多个元素,或者完全清空队列。
内置的不阻塞队列:
*PriorityQueue(优先级队列)
*ConcurrentLinkedQueue(基于链表的并发队列)(判断是否有元素可以使用isEmpty()方法,不要用size()>0)实现阻塞接口的:
*ArrayBlockingQueue:(基于数组的并发阻塞队列)
*LinkedBlockingQueue :(基于链表的FIFO阻塞队列)
*PriorityBlockingQueue :(带优先级的无界阻塞队列)
*DelayQueue :(延期阻塞队列)(阻塞队列实现了BlockingQueue接口)
*SynchronousQueue :(并发同步阻塞队列) -
阻塞队列操作:
add:增加一个元索 , 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
offer:添加一个元素并返回true,如果队列已满,则返回false
put:添加一个元素,如果队列满,则阻塞remove:移除并返回队列头部的元素,如果队列为空,则抛出一个NoSuchElementException异常
poll:移除并返问队列头部的元素, 如果队列为空,则返回null
take:移除并返回队列头部的元素,如果队列为空,则阻塞element:返回队列头部的元素, 如果队列为空,则抛出一个NoSuchElementException异常
peek:返回队列头部的元素,如果队列为空,则返回null
( 说明:如果是定长队列,元素没满的时候任何一个插入方法都可以,但是如果满了,add就会报错,offer不会报错,会返回false,put会阻塞等待( 类似wait() ),直到有空位立马插入。(remove,poll,take)同插入原理一样,peek()和element()方法仅仅查询头部元素,不会移除 )
- 生产者、消费者代码示例:
package com.example.demo.poolTest;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
class Producer implements Runnable{
private ArrayBlockingQueue<Integer> queue;
private boolean flag = true;
private Integer count = 0;
public Producer(ArrayBlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("生产者启动成功!");
while (flag) {
count = count + 1;
try {
boolean offer = queue.offer(count);
if(!offer){
System.out.println("已经放满啦~");
}else{
System.out.println( Thread.currentThread().getName() + ":生产者放入" + this.count);
}
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("生产者停止!");
}
public void stop() {
this.flag = false;
}
}
class Consumer implements Runnable{
private ArrayBlockingQueue<Integer> queue;
private boolean flag = true;
public Consumer(ArrayBlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("消费者启动成功!");
while (flag) {
try {
Integer data = queue.poll(2, TimeUnit.SECONDS);
if(data == null){
flag = false;
System.out.println("已经取完啦~");
}else{
System.out.println( Thread.currentThread().getName() + ":消费者取出" + data);
}
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class testQueue {
public static void main(String[] args) throws Exception{
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(3);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
Thread producerThread = new Thread(producer);
Thread consumerThread = new Thread(consumer);
producerThread.start();
consumerThread.start();
Thread.sleep(5000);
producer.stop();
}
}