/**
* 对列也是一种数据结构: 先入先出 效率和栈一样 : O(1)时间复杂度
* 批量的数据收集和处理的时候: 多会用到队列 : 类似的各种消息中间件儿: RabbitMQ等
*
* 例如并发情景下: 针对客户端的并发请求在队列入端接收
* 在队列出口处可以采用多线程处理:高效利用CPU
* 再通过分布式、负载均衡分发到各个对应的服务器上等进行一个Request的处理
*
* 队列有队头和队尾: 可以分为两种:阻塞队列和非阻塞队列
* JDK中一般常用阻塞队列:非阻塞略微麻烦,需要自定义wait()和 notify(),特殊情况还要注意加锁
*
*/
阻塞队列如下:
import java.util.concurrent.ArrayBlockingQueue;
/***
* 从Java 1.5之后,在java.util.concurrent包下提供:
** ArrayBlockingQueue:基于数组实现的一个阻塞队列
* 在创建ArrayBlockingQueue对象时必须制定容量大小
* 并且可以指定公平性与非公平性,默认情况下为非公平的
* 即不保证等待时间最长的队列最优先能够访问队列。
*/
public class BlockQueue {
public static void main(String[] args) {
new SCZ().start();
new XFZ().start();
}
//阻塞队列需要指定队列容量
public static int maxCupSize = 10 ;
public static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(maxCupSize);
/**
* 生产者模型
*/
static class SCZ extends Thread{
@Override
public void run() {
while(true){
try {
queue.put(1);
System.out.println("容量剩余: "+ (maxCupSize - queue.size() ));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者模型
*/
static class XFZ extends Thread{
@Override
public void run() {
while(true){
try {
queue.take();
System.out.println("队列取出后剩余: "+ queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
关于java.util 中提供的队列的方法们:
/***
*
* 同样对于队列常见的方法:这几个方法阻塞队列和非阻塞队列中均可使用 :
* add(E e): 将元素e插入队尾,如果插入成功,返回true,如果失败(队列已满)抛出异常;
*
* public abstract class AbstractQueue<E>: 中 add 方法源码如下:
* public boolean add(E e) {
* if (offer(e)) // 调用 offer(E e ) 方法
* return true;
* else
* throw new IllegalStateException("Queue full");
* }
*
* remove() : 将队头的元素移除,如果成功返回true,如果失败(队列为空)抛出异常;
* offer(E e) : 将元素插入到队列末尾,如果插入成功,返回true,如果失败(队列已满)返回false;
* poll() : 获取队头元素并移除,成功: 返回队头元素 失败: 返回null
* peek() : 获取队头元素,成功:返回队头元素 失败: 返回null
*
*
*/
阻塞队列包括了非阻塞队列中的大部分方法,如上五个方法中都进行了同步措施,除此之外,还提供了另外四个常用的方法
* 阻塞队列包括了非阻塞队列中的大部分方法,如上五个方法中都进行了同步措施
* 除此之外,还提供了另外四个常用的方法
*
* put(E e) 方法: 用来向队尾插入元素,如果队列已满则等待
* take() : 从队头取元素,如果队列为空,则等待
* offer(E e , long timeout, TimeUnit timeUnit): 从队尾存入元素,如果队列已满,则等待一定时间
* 时间到达仍未成功,返回false ,成功则返回true
* poll(long timeout , TimeUnit unit ): poll方法从队头取元素,如果队列为空则等待一定时间
* 时间到达仍未成功,返回null ,成功则返回取到的元素对象
阻塞队列生产消费模型
public class QueueTestBlocking {
private static int maxSize = 10 ;
private static PriorityQueue<Integer> queue = new PriorityQueue<>(maxSize);
/**
* 消费者
*/
static class Product extends Thread {
@Override
public void run() {
while (true) {
synchronized (queue){
while (queue.size()==maxSize) {
System.out.println("队列满了, 等待 ... ");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer(1);
System.out.println("队列插入数据,剩余空间:"+ (maxSize-queue.size()));
queue.notify();
}
}
}
}
static class Cast extends Thread{
@Override
public void run() {
while (true){
synchronized (queue){
while (queue.size()==0){
try {
queue.wait();
System.out.println("队列没数据了....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll();
System.out.println("从队列取出一个元素:" + queue.size());
queue.notify();
}
}
}
}
public static void main(String[] args) {
Product p = new Product();
p.start();
new Cast().start();
}
}
优先级阻塞队列(特殊)PriorityBlockingQueue
优先级队列中按照关键词有序队列:插入会插入到合适的位置,保证有序性
插入需要O(N),删除需要O(1)
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
public class YouXianJiQueue {
public static void main(String[] args) {
sort();
}
static void sort(){
Queue<Integer> queue = new PriorityQueue<>(7);
Random random = new Random();
//插入数据
for (int i = 0 ; i < 7 ; i ++ ) {
queue.offer(random.nextInt(100));
}
//读数据
for (int i = 0 ; i < 7 ; i ++ ) {
Integer poll = queue.poll();
System.out.println(poll);
}
}
}
也可以用对象的某个属性排序:Comparator 属性需要构建传入构造方法new PriorityQueue<User>(7,idSort);
延时阻塞队列DelayQueue
image.png
网友评论