java阻塞队列数据操作详解

文章目录

      • 阻塞队列
        • 消费者阻塞
        • 生产者阻塞
        • 插入操作
        • 获取数据操作

阻塞队列

队列是一种只允许在标的前端进行删除操作,而在表的藕断进行插入操作的线性表。阻塞队列和一班队列的不同之处在于阻塞队列是阻塞的,这里的阻塞指的是操作队列的线程的一种状态。在阻塞队列中,线程阻塞有如下两种情况。

消费者阻塞

在队列为空时,消费者端的线程都会被自动阻塞(挂起),直到有数据放入队列,消费者线程会被自动唤醒并消费数据。

生产者阻塞

在队列已满且没有可用空间时,生产者端的线程都会被自动阻塞(挂起),直到队列中有空的位置腾出,线程会被自动唤醒并生产数据。
阻塞队列的主要操作
阻塞队列的主要操作 有插入操作和移除操作。插入操作有add(e),offer(e),put(e),offer(e,time,unit),移除操作有remove(),pull()

插入操作

  1. public abstract boolean add(E paramE): 将指定的元素插入队列中,在成功时返回true,如果当前没有可用的空间,则抛出IlegalStateException。如果元素师null,则抛出NullPointException异常。JDK源码的实现如下:

    		public boolean add(E e){
    		
    		//添加一个数据,如果成功,则返回true
    		if(offer(e))
    		return true;
    		//如果失败返回异常
    		else
    		throw new IllegalStateException("Queue full");
    		}
    			
    
  2. public abstract boolean offer(E paramE): 将指定的元素插入队列中,在成功时返回true,如果当前没有可用的空间,则返回false。JDK源码的实现如下:

    				public boolean offer(E e){
    				checkNotNull(e);
    				final ReentranLock lock = this.lock;
    				lock.lock();//获取锁try
    				try{
    				if(count == items.length)
    				//如果队列满了,则返回false
    				return false;
    				else{
    				enqueue(e);//如果队列有空间,则将元素加入队列中
    				return true;
    						}
    					}finally{
    					lock.unlock();
    					}
    				}
    
  3. offer(E o,long timeout, TimeUnit unit):将指定的元素插入队列中,可以设定等待的时间,如果在设定的等待时间内仍不能像队列中加入元素,则返回false。

  4. public abstract void put(E paramE)throws InterruptedException:将指定的元素插入队列中,如果对烈烈已经满了,则阻塞,等待可用的队列空间的释放,直到有可用的队列空间释放且插入成功为止,JDK源码的实现如下

    		 public void put(E e)throws InterruptedException {
    		 		
    				checkNotNull(e);
    						
    				final ReentrantLock lock =this.lock;
    				
    				lock.lockInterruptibly();
    				
    				try{
    				
    				while(count == items.length)//阻塞等待可用空间的释放
    				
    				notFull.await();
    				
    				enqueue(e);//将元素加入队列中
    				
    				}finally{
    				
    				lock.lock();
    				
    				}
    			}
    		
    

获取数据操作

  1. poll();取走队列队首的对象,如果取不到数据,则返回null。JDK源码的实现如下:
    		public E poll(){
    			
    			final ReenTranLock lock= this.lock;
    			
    			lock.lock();
    		
    			try{
    			//如果获取不到数据count == 0 ,则返回null 
    			return (count ==0 )? null : dequeue();
    			
    			}finally{
    			
    			lock.unlock();//释放锁
    			
    			}
    		
    		}
    
  2. poll(long timeout, TimeUnit unit):取走队列队首的对象,如果在指定的时间内队列有数据可取,则返回队列中的数据,否则等待一定时间,在等待超时并且没有数据可取时,返回null。
  3. take():取走队列队首的对象,入股哦队列为空,则进入阻塞状态等待,直到队列有心的数据被加入,在集市去除新加入的数据,JDK源码的实现如下:
    		public E take() throws InterruptedException{
    			final ReentrantLock lock = this.lock;
    			lock.lockInterruptibly();//获取独占锁
    			try{
    			//如果队列为空,则进入阻塞状态,直到能取到数据为止
    			while(count==0{
    			notEmpty.await();
    			return dequeue();//取出元素}
    				finally{
    			lock.lock();
    					}
    				}
    			}
    		}
    
  4. drainTo(Collection collection): 一次性从队列中批量获取所有可用的数据对象,同事可以指定获取数据的个数,通过该方法可以提升获取数据的效率,避免多次频繁操作引起的队列锁定。JDK源码的实现如下:
    		public int drainTo(Collection<? super E> c,int maxElemenets){
    			checkNotNull(c);
    			if(c == this)
    				throw new IllegalArgumentException();
    			if(maxElemenet <= 0)
    			 return 0;
    			 final Object[] items = this.items;
    			 final ReentrantLock lock = this.lock;
    			// 获取锁操作lock.loc看();
    			try{
    				int n =Math.min(maxElemnent, count)//获取队列中指定个数的元素
    				int take = takeIndex;
    				int i = 0try{
    			while(i < n){
    					@SuppressWarnings("unchecked")
    				 	E x = (E) items[take];
    		 			c.add(x);
    					 items[take]=null;
    					 if (++take == items.length)
    			 			take =0;
    					 i++;		
    				}
    			return n;
    			
    			}finally{
    			//Restore inveriants even if c.add() threw// 如果在drainTo过程中有新的数据加入,则处理该数据
    			if(i>0{
    			count -=i;
    			takeIndex = take;
    			if( itrs !=null){
    			if(count ==0)
    				itrs.queueIsEmpty();
    				else if( i > take)
    				itrs.takeIndexWrapped();
    				
    				}
    				for(;i>0&& lock.hasWaiters(notFull);i--)
    					notFull.signal();//唤醒等待的生产者线程
    				}
    			}
    		}finally{
    				lock.unlock(;//释放锁
    				}
    		}
    

你可能感兴趣的:(javaee)