赞
踩
队列是一种常见的数据结构,它按照先进先出(FIFO)的原则管理元素。在 Java 中,队列通常是通过链表或数组实现的,不同的实现类在内部数据结构和操作上可能有所不同。
1.数据结构:队列的基本数据结构可以是链表或数组。链表实现的队列(如 LinkedList)允许高效地在两端进行添加和删除操作,而数组实现的队列(如 ArrayDeque)则可以更快地随机访问元素。
2.入队操作:将元素添加到队列的末尾称为入队操作。在链表实现中,入队操作涉及将新元素链接到链表的末尾;而在数组实现中,入队操作将新元素添加到数组的末尾,并更新队尾指针。
3.出队操作:从队列的头部移除元素称为出队操作。无论是链表还是数组实现,出队操作都涉及从队列的头部移除元素,并更新队头指针。
4.队列的大小:队列的大小可以根据添加和删除的元素数量来动态调整。在使用链表实现时,可以方便地添加或删除元素而不需要重新分配内存;而在使用数组实现时,可能需要进行数组扩容或缩小操作
1.双向链表结构: 每个元素都包含对其前一个元素和后一个元素的引用,这样可以轻松地在链表中插入和删除元素。
2.支持索引访问: 虽然链表的随机访问效率较低,但LinkedList仍然支持根据索引访问元素,可以使用get(int index)方法获取指定位置的元素。
3.支持头部和尾部操作: LinkedList实现了Deque接口,因此支持在头部和尾部添加、移除元素的操作,如offerFirst(E e)、offerLast(E e)、pollFirst()、pollLast()等。
4.非线程安全: LinkedList不是线程安全的,如果多个线程同时访问一个LinkedList实例并且至少有一个线程修改了列表的结构,那么必须通过外部同步来确保该LinkedList在并发环境中的安全性。
5.迭代器支持: LinkedList提供了ListIterator接口的实现,可以通过迭代器遍历链表中的元素。
可以查看文档比较多
百度网盘 获取JDKAPI文档
链接:https://pan.baidu.com/s/1Z5mL0vVbXX1mMS8UqRaa6Q
提取码:2ktk
LinkedList<String> linkedList = new LinkedList<>(); // 添加元素到链表尾部 linkedList.add("A"); linkedList.add("B"); linkedList.add("C"); // 在链表头部添加元素 linkedList.addFirst("X"); // 在链表尾部添加元素 linkedList.addLast("Y"); // 移除链表头部元素 linkedList.removeFirst(); // 移除链表尾部元素 linkedList.removeLast(); // 获取链表的第一个元素 String first = linkedList.getFirst(); // 获取链表的最后一个元素 String last = linkedList.getLast(); // 遍历链表元素 for (String element : linkedList) { System.out.println(element); }
1.基于堆实现: PriorityQueue通常基于堆数据结构实现,通常是一个最小堆(最小优先级队列),也可以通过提供自定义的比较器来创建最大堆(最大优先级队列)。
2.元素排序: 元素可以按照它们的自然顺序(如果它们实现了Comparable接口)或者根据提供的Comparator进行排序。
3.动态增长: PriorityQueue的大小可以动态增长,可以根据需要添加任意数量的元素。
4.不允许null元素: PriorityQueue不允许插入null元素,否则会抛出NullPointerException。
5.不是线程安全的: PriorityQueue不是线程安全的,如果多个线程同时访问一个PriorityQueue实例并且至少有一个线程修改了队列的结构,那么必须通过外部同步来确保该PriorityQueue在并发环境中的安全性。
// 创建一个最小堆(最小优先级队列) PriorityQueue<Integer> minHeap = new PriorityQueue<>(); // 添加元素到优先级队列 minHeap.offer(5); minHeap.offer(3); minHeap.offer(8); minHeap.offer(1); // 获取并移除队列中的最小元素 int minElement = minHeap.poll(); System.out.println("最小元素:" + minElement); // 获取但不移除队列中的最小元素 int peekMinElement = minHeap.peek(); System.out.println("最小元素(但不移除):" + peekMinElement); // 创建一个最大堆(最大优先级队列),使用自定义比较器 PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a); // 添加元素到优先级队列 maxHeap.offer(5); maxHeap.offer(3); maxHeap.offer(8); maxHeap.offer(1); // 获取并移除队列中的最大元素 int maxElement = maxHeap.poll(); System.out.println("最大元素:" + maxElement);
1.零容量:SynchronousQueue 是一个零容量的队列,它不保存任何元素。插入操作(offer)只有在有线程等待获取元素时才会成功,否则会一直阻塞。
2.直接传递:生产者线程通过 put 方法插入元素时会阻塞,直到有消费者线程调用 take 方法获取这个元素。这种机制可以实现直接传递数据,而不需要中间的缓冲区。
3.公平性:SynchronousQueue 可以选择是否公平地进行元素获取。在公平模式下,如果多个消费者线程同时等待获取元素,队列会按照线程等待的先后顺序来分配元素。
4.应用场景:适合用于生产者和消费者之间的直接传递数据的场景,例如线程池任务分配、消息传递等。
BlockingQueue<Object> synchronousQueue = new SynchronousQueue<>();//同步队列 //添加元素 new Thread(()->{ try { System.out.println(Thread.currentThread().getName() + "put 1"); synchronousQueue.put(1); System.out.println(Thread.currentThread().getName() + "put 2"); synchronousQueue.put(2); System.out.println(Thread.currentThread().getName() + "put 3"); synchronousQueue.put(3); } catch (InterruptedException e) { throw new RuntimeException(e); } },"线程A").start(); //移除元素 new Thread(()->{ try { TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + "take" + synchronousQueue.take()); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + "take" + synchronousQueue.take()); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + "take" + synchronousQueue.take()); } catch (InterruptedException e) { throw new RuntimeException(e); } },"线程B").start();
多线程环境下,BlockingQueue通常用于实现生产者-消费者模式,其中生产者线程将数据放入队列,而消费者线程从队列中取出数据进行处理。
当队列为空时,消费者线程试图从队列中取出元素时会被阻塞,直到队列中有可用元素为止;而当队列已满时,生产者线程试图向队列中放入元素时也会被阻塞,直到队列有空闲位置为止。
1.ArrayBlockingQueue: 基于数组实现的有界阻塞队列,必须指定队列的容量,适合固定大小的线程池。
2.LinkedBlockingQueue: 基于链表实现的可选有界或无界阻塞队列,默认情况下是无界的,但也可以指定容量创建有界队列。
3.PriorityBlockingQueue: 是一个支持优先级排序的无界阻塞队列,元素按照它们的自然顺序或者根据提供的Comparator进行排序。
4.DelayQueue: 是一个支持延迟元素的无界阻塞队列,其中的元素只有在其指定的延迟时间到达后才能被获取。
5.SynchronousQueue: 是一个不存储元素的阻塞队列,每个插入操作必须等待另一个线程进行相应的删除操作,适合传递性场景。
1.put(E e): 将指定的元素插入到队列中,如果队列已满,则阻塞直到队列有空闲位置。
2.take(): 获取并移除队列的头部元素,如果队列为空,则阻塞直到队列中有可用元素。
3.offer(E e, long timeout, TimeUnit unit): 将指定的元素插入到队列中,如果队列已满,则阻塞直到指定的超时时间。
4.poll(long timeout, TimeUnit unit): 获取并移除队列的头部元素,如果队列为空,则阻塞直到指定的超时时间。
5.remainingCapacity(): 返回队列中剩余的可用空间。
BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); //添加元素 System.out.println(blockingQueue.add("AAAA")); System.out.println(blockingQueue.add("BBBB")); System.out.println(blockingQueue.add("CCCC")); //获取队列首位元素 System.out.println(blockingQueue.element()); //打印元素 blockingQueue.stream().forEach(System.out::print); System.out.println(); //抛出异常:java.lang.IllegalStateException: Queue full // blockingQueue.add("DDDD"); //移除元素 System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.element()); System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.remove()); blockingQueue.stream().forEach(System.out::print); //抛出异常:java.util.NoSuchElementException System.out.println(blockingQueue.element()); //抛出异常:java.util.NoSuchElementException // System.out.println(blockingQueue.remove());
BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); //添加元素 System.out.println(blockingQueue.offer("AAAA")); System.out.println(blockingQueue.offer("BBBB")); System.out.println(blockingQueue.offer("CCCC")); //检测队首元素 System.out.println(blockingQueue.peek()); //打印元素 blockingQueue.stream().forEach(System.out::print);System.out.println(); //不抛出异常 返回 false // System.out.println(blockingQueue.offer("DDDD")); System.out.println(blockingQueue.poll()); //检测队首元素 System.out.println(blockingQueue.peek()); System.out.println(blockingQueue.poll()); System.out.println(blockingQueue.poll()); //打印元素 blockingQueue.stream().forEach(System.out::print);System.out.println(); //检测队首元素 null 无异常 System.out.println(blockingQueue.peek()); //null 不抛出异常 // System.out.println(blockingQueue.poll());
BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); //添加元素 blockingQueue.put("AAAA"); blockingQueue.put("BBBB"); blockingQueue.put("CCCC"); //打印元素 blockingQueue.stream().forEach(System.out::print);System.out.println(); //阻塞线程执行,直到元素能够添加进去 // blockingQueue.put("DDDD"); System.out.println(blockingQueue.take()); System.out.println(blockingQueue.take()); System.out.println(blockingQueue.take()); //阻塞线程执行,直到能够消费到元素 System.out.println(blockingQueue.take());
BlockingQueue blockingQueue = new ArrayBlockingQueue<>(3); //添加元素 System.out.println(blockingQueue.offer("AAAA")); System.out.println(blockingQueue.offer("BBBB")); System.out.println(blockingQueue.offer("CCCC")); //检测队首元素 System.out.println(blockingQueue.peek()); //打印元素 blockingQueue.stream().forEach(System.out::print);System.out.println(); //不抛出异常 等待超过两秒 返回 false System.out.println(blockingQueue.offer("DDDD",2,TimeUnit.SECONDS)); System.out.println(blockingQueue.poll()); //检测队首元素 System.out.println(blockingQueue.peek()); System.out.println(blockingQueue.poll()); System.out.println(blockingQueue.poll()); //打印元素 blockingQueue.stream().forEach(System.out::print);System.out.println(); //检测队首元素 null 无异常 System.out.println(blockingQueue.peek()); //null 不抛出异常 超过两秒 System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
不足之处,望海涵!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。