技术问答-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接口的简单聚集机制(缓存线程 使用的就是它)

三、方法
返回方法说明
booleanadd(E)添加元素,如果队列已满,抛出IllegalStateException
booleanoffer(E)与add一样,add就是调用的offer方法
Eremove()移除并返回队列头部元素,如果队列为空则抛出NoSuchElementException
Eelement()返回队列头部元素,如果队列为空则抛出NoSuchElementException
Epoll()移除并返回队列头部元素,如果队列为空则返回null
Epeek()返回队列头部元素 如果队列为空返回null
voidput(E)添加一个元素 如果队列满了 则阻塞
Etake()移除并返回队列头部元素,如果队列为空 则阻塞
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的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程