java阻塞队列

BlockingQueue主要方法java

java阻塞队列应用于生产者消费者模式、消息传递、并行任务执行和相关并发设计的大多数常见使用上下文。
       BlockingQueue在Queue接口基础上提供了额外的两种类型的操做,分别是获取元素时等待队列变为非空和添加元素时等待空间变为可用。
       BlockingQueue新增操做的四种形式:数组

add        增长一个元索                     若是队列已满,则抛出一个IIIegaISlabEepeplian异常
remove   移除并返回队列头部的元素    若是队列为空,则抛出一个NoSuchElementException异常
element  返回队列头部的元素             若是队列为空,则抛出一个NoSuchElementException异常
offer       添加一个元素并返回true       若是队列已满,则返回false
poll         移除并返问队列头部的元素    若是队列为空,则返回null
peek       返回队列头部的元素             若是队列为空,则返回null
put         添加一个元素                      若是队列满,则阻塞
take        移除并返回队列头部的元素     若是队列为空,则阻塞安全

offer(E o, long timeout, TimeUnit unit);  //将指定的元素插入此队列中,若是没有可用空间,将等待指定的等待时间(若是有必要)。 
poll(long timeout, TimeUnit unit);  //检索并移除此队列的头部,若是此队列中没有任何元素,则等待指定等待的时间(若是有必要)。数据结构

 上述方法中主要用到的是put()和take()方法,也只有这两个方法具备阻塞等待功能,另外BlockingQueue 不接受 null 元素。试图 add、put 或 offer 一个 null 元素时,某些实现会抛出 NullPointerException。null 被用做指示 poll 操做失败的警惕值。
       BlockingQueue 能够定义为限定容量的队列,它有一个 remainingCapacity容量值,超出此容量,便没法无阻塞地 put 额外的元素。也能够定义为没有容量限制的队列,没有容量约束的 BlockingQueue 老是报告 Integer.MAX_VALUE 的剩余容量。
       BlockingQueue 实现是线程安全的。全部排队方法均可以使用内部锁定或其余形式的并发控制来自动达到它们的目的。多线程

BlockingQueue成员详细介绍并发

LinkedBlockingQueue的容量是没有上限的(说的不许确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),可是也能够选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。而LinkedBlockingQueue之因此可以高效的处理并发数据,还由于其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的状况下生产者和消费者能够并行地操做队列中的数据,以此来提升整个队列的并发性能。
做为开发者,咱们须要注意的是,若是构造一个LinkedBlockingQueue对象,而没有指定其容量大小,LinkedBlockingQueue会默认一个相似无限大小的容量(Integer.MAX_VALUE),这样的话,若是生产者的速度一旦大于消费者的速度,也许尚未等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。dom


ArrayBlockingQueue在构造时须要指定容量, 并能够选择是否须要公平性,若是公平参数被设置true,等待时间最长的线程会优先获得处理(其实就是经过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操做)。一般,公平性会使你在性能上付出代价,只有在的确很是须要的时候再使用它。它是基于数组的阻塞循环队列,此队列按 FIFO(先进先出)原则对元素进行排序。ArrayBlockingQueue在生产者放入数据和消费者获取数据,都是共用同一个锁对象,由此也意味着二者没法真正并行运行,这点尤为不一样于LinkedBlockingQueue;高并发


PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList同样,因此在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,可是因为资源被耗尽,因此试图执行添加操做可能会致使 OutOfMemoryError),可是若是队列为空,那么取元素的操做take就会阻塞,因此它的检索操做take是受阻的。另外,往入该队列中的元 素要具备比较能力。性能


DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。若是延迟都尚未期满,则队列没有头部,而且poll将返回null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不容许使用 null 元素。spa

代码实例

package study;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueTest {  
    public static void main(String[] args) {  
        final BlockingQueue queue = new ArrayBlockingQueue(3);  
        for(int i=0;i<2;i++){  
            new Thread(){  
                public void run(){  
                    while(true){  
                        try {  
                        Thread.sleep((long)(Math.random()*1000));  
                        System.out.println(Thread.currentThread().getName() + "准备放数据!");                              
                            queue.put(1);  
                            System.out.println(Thread.currentThread().getName() + "已经放了数据," +   "队列目前有" + queue.size() + "个数据");  
                        } catch (InterruptedException e) {  
                            e.printStackTrace();  
                        }  
                    }  
                }  
                  
            }.start();  
        }  
        new Thread(){  
            public void run(){  
                while(true){  
                    try {  
                    //将此处的睡眠时间分别改成100和1000,观察运行结果  
                    Thread.sleep(1000);  
                    System.out.println(Thread.currentThread().getName() + "准备取数据!");  
                    queue.take();  
                    System.out.println(Thread.currentThread().getName() + "已经取走数据," +   
                                "队列目前有" + queue.size() + "个数据");          
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }  
        }.start();            
    }  
}

使用阻塞队列两个显著的好处就是:多线程操做共同的队列时不须要额外的同步,另外就是队列会自动平衡负载,即那边(生产与消费两边)处理快了就会被阻塞掉,从而减小两边的处理速度差距。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择。

相关文章
相关标签/搜索