技术问答-10 java中的集合(5)-Queue
2021/4/13 20:55:41
本文主要是介绍技术问答-10 java中的集合(5)-Queue,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Queue
一、Queue是什么
Queue是一种队列结构集合,用来储存将要进行处理的元素,一般会以FIFO的方式排序元素,但这不是必须的。比如优先级队列就是一个例外,优先级队列是以元素的值来排序。但是无论怎么样,每个queue的实现都必须制定它的排序属性。queue通常不定义元素的equal和hashCode
二、Queue的实现
1. 非阻塞
LinkedList 实现了Queue和AbstractQueue
PriorityQueue
PriorityQueue类 实质上维护了一个有序列表。加入到Queue中的元素根据他们天然排序(通过实现Comparable实现)或者根据传递给构造函数的Comparator实现来定位,它的增加操作不是原子操作,没有添加任何锁,所以它是线程不安全的。ConcurrentLinkedQueue
ConcurrentLinkedQueue是基于链接节点的、线程安全的队列,并发访问不需要同步,
它是非阻塞队列,使用CAS非阻塞算法实现
推荐看看
1. 阻塞
java.util.concurrent中加入了BlockingQueue接口和五个阻塞队列,它实质上就是一种带有一点扭曲的FIFO数据结构。不是立即从队列添加或者删除元素,线程操作阻塞,直到有空间或元素可用ArrayBlockingQueue :一个由数组支持的有界队列
LinkedBlockingQueue:一个由链表节点支持的可选有界的队列(固定线程 使用的就是它)
PriorityBlockingQueue:一个由优先级堆支持的***优先级队列
DelayQueue: 一个由优先级堆的、基于时间的调度队列 (定时线程 使用的就是它)
SynchronousQueue:一个利用BlockingQueue接口的简单聚集机制(缓存线程 使用的就是它)
三、方法
返回 | 方法 | 说明 |
---|---|---|
boolean | add(E) | 添加元素,如果队列已满,抛出IllegalStateException |
boolean | offer(E) | 与add一样,add就是调用的offer方法 |
E | remove() | 移除并返回队列头部元素,如果队列为空则抛出NoSuchElementException |
E | element() | 返回队列头部元素,如果队列为空则抛出NoSuchElementException |
E | poll() | 移除并返回队列头部元素,如果队列为空则返回null |
E | peek() | 返回队列头部元素 如果队列为空返回null |
void | put(E) | 添加一个元素 如果队列满了 则阻塞 |
E | take() | 移除并返回队列头部元素,如果队列为空 则阻塞 |
package along;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.DelayQueue;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.PriorityBlockingQueue;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.TimeUnit;import com.mysql.jdbc.TimeUtil;public class javaTest {public static void main(String[] args) { //ArrayBlockingQueue ArrayBlockingQueue<Integer> aq = new ArrayBlockingQueue<Integer>(10);for(int i=0;i<11;i++){//aq.add(i);}//java.lang.IllegalStateException: Queue full//LinkedBlockingQueue *** 有界 LinkedBlockingQueue<Integer> lq1 = new LinkedBlockingQueue<Integer>(); LinkedBlockingQueue<Integer> lq2 = new LinkedBlockingQueue<Integer>(10);//PriorityBlockingQueue PriorityBlockingQueue<Integer> pq = new PriorityBlockingQueue<Integer>(); pq.add(2);pq.add(8);pq.add(1);pq.add(22); Integer i=null;while((i = pq.poll()) != null){ System.out.println(i);}//1 2 8 22 按顺序排列 DelayQueue<DelayedTest> dq = new DelayQueue<DelayedTest>();//这里传入的参数是毫秒 他会转换成秒 再加上当前系统时间 DelayedTest d1 = new DelayedTest(1, "111111111111111111111", 10000); DelayedTest d2 = new DelayedTest(2, "222222222222222222222", 20000); DelayedTest d3 = new DelayedTest(3, "333333333333333333333", 30000); dq.add(d1); dq.add(d2); dq.add(d3);try{// System.out.println(dq.take());//元素被添加到队列 10秒后输出// System.out.println(dq.take());//元素被添加到队列 20秒后输出// System.out.println(dq.take());//元素被添加到队列 30秒后输出}catch(Exception e){ System.out.println("error");}//SynchronousQueue 这个东西很神奇 它的作用是如果想add一个元素进去 必须有take在等待 也就是如果生产想要push必须等待消费者的take SynchronousQueue<Integer> sq =new SynchronousQueue<>();// sq.add(12);//没有线程take这里是没有办法加进去的new Thread(new Runnable() {public void run() {try{ System.out.println("元素:"+sq.take());}catch(Exception e){ e.printStackTrace();}}}).start(); //主线程等待2秒钟try { TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e1) { e1.printStackTrace();}new Thread(new Runnable() {public void run() {try{ sq.add(1111);}catch(Exception e){ e.printStackTrace();}}}).start();//但是用put不会报错 他会等着take操作 没有take他不会put成功try { sq.put(1212);} catch (InterruptedException e) { e.printStackTrace();} /** * iterator() 永远返回空,因为里面没东西。 * peek() 永远返回null。 * put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。 * offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。 * offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。 * take() 取出并且remove掉queue里的element(认为是在queue里的。。。),取不到东西他会一直等。 * poll() 取出并且remove掉queue里的element(认为是在queue里的。。。),只有到碰巧另外一个线程正在往queue里offer数据或者put数据的时候,该方法才会取到东西。否则立即返回null。 * poll(2000, TimeUnit.SECONDS) 等待指定的时间然后取出并且remove掉queue里的element,其实就是再等其他的thread来往里塞。 * isEmpty()永远是true。 * remainingCapacity() 永远是0。 * remove()和removeAll() 永远是false。 */// SynchronousQueue 内部没有容量,但是由于一个插入操作总是对应一个移除操作,反过来同样需要满足。// 那么一个元素就不会再SynchronousQueue 里面长时间停留,一旦有了插入线程和移除线程,元素很快就从插入线程移交给移除线程。//也就是说这更像是一种信道(管道),资源从一个方向快速传递到另一方 向。//显然这是一种快速传递元素的方式,也就是说在这种情况下元素总是以最快的方式从插入着(生产者)传递给移除着(消费者),//这在多任务队列中是最快处理任务的方式。//在线程池里的一个典型应用是Executors.newCachedThreadPool()就使用了SynchronousQueue,//这个线程池根据需要(新任务到来时)创建新的线程,如果有空闲线程则会重复使用,线程空闲了60秒后会被回收。}}
这篇关于技术问答-10 java中的集合(5)-Queue的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-25Java语音识别项目入门:新手必读指南
- 2024-11-25Java语音识别项目入门:轻松开始你的第一个语音识别项目
- 2024-11-25Java语音识别项目入门详解
- 2024-11-25Java语音识别项目教程:从零开始的详细指南
- 2024-11-25JAVA语音识别项目教程:初学者指南
- 2024-11-25Java语音识别项目教程:初学者指南
- 2024-11-25JAVA云原生入门:新手指南与基础教程
- 2024-11-25Java云原生入门:从零开始的全面指南
- 2024-11-25Java云原生入门:新手必读教程
- 2024-11-25JAVA云原生教程:新手入门及实战指南