1.首先,Queue接口与List、set同级别,Queue不熟悉但是List和Set都很熟悉了,Queue也继承了Collection接口,LinkedList实现了Queue接口;
2. java.util.Queue接口是在java5中加入的,在java多线程应用中,使用率很高,多数生产消费模型的首选数据结构就是队列,java提供的线程安全的Queue可以分为阻塞队列(典型:BlockingQueue)和非阻塞队列(典型:ConcurrentLinkedQueue),在实际应用中要根据实际需要选用阻塞队列或非阻塞队列;
3.LInkedBlockingQueue是一个基于已链接节点的,范围任意的BlockingQueue的实现是基于链表的队列;按先进先出的顺序;新元素插入到队列的尾部,队列检索操作和获得位于队列头部的元素,链接队列的吞吐量常常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低;使用中要防止队列过度扩展,如果未指定容量,则等于Integer.MAX_VALUE.除非插入节点会使队列超出容量,否则每次插入后会动态地创建链接节点;
使用阻塞队列的好处,多线程操作共同的队列时不需要额外的同步,另外就是队列会自动平衡负载,即那边(生产与消费两边)处理快了就会被阻塞掉,从而减少两边的处理数度差距;
4.队列的2个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素;
5.方法:add 增加一个元素 如果队列已满,则抛出异常;
remove移除并返回队列头部的元素 如果队列已空 则抛出NoSuchElementException异常;
element返回队列头部的元素 如果队列为空 则抛出NoSuchElementException异常;
offer添加一个元素并返回true 如果队列已满 则返回false;
poll移除并返回队列头部的元素 如果队列为空 则返回null;
peek返回队列头部的元素 如果队列为空 则返回null;
put添加一个元素 如果队列满 则阻塞;
take移除并返回队列头部的元素 如果队列为空 则阻塞;
clear从队列彻底移除所有元素
6.注意事项:
1)如果未指定容量,默认容量为Integer.MAX_VALUE,容量范围可以在构造方法参数中指定作为防止队列过度扩展;
2)不接受null;如:在element时队列为空抛出异常说明是null时是不正确的;
3)实现了BlockingQueue接口;
4)实现了Collection和Iterator接口的所有可选方法;
5)项目中使用:
LinkedBlockingQueue<A> queue = (LinkedBlockingQueue<A>)getCurrentSessionAttribute(request,"viewedPackageQueue");
if(queue == null){
queue = new LinkedBlockingQueue<A>();
}
if(queue.size() == 5 && !isContain(A,queue)){
queue.poll();
}
if(!isContain(A,queue)){
queue.offer(A);
}
setCurrentSessionAttribute(request,"viewedPackageQueue",queue);
/**
* 封装获取Session属性
*
* @param request
* @param name
* @return
*/
protected Object getCurrentSessionAttribute(HttpServletRequest request,String name){
return WebUtils.getSessionAttribute(request, name);
}
/**
* 封装设置Session属性
*
* @param request
* @param name
* @return
*/
protected void setCurrentSessionAttribute(HttpServletRequest request,String name, Object value){
WebUtils.setSessionAttribute(request, name, value);
}
7.ConcurrentLinkedQueue<E>:java.util.concurrent
一个基于链接节点的、无界的、线程安全的队列。FIFO;
当多线程共享一个公共collection时,ConcurrentLinkedQueue是一个恰当的选择,此队列不允许null元素;
扩展:
并发编程中的一种编程方式是把任务拆分为一些小的任务,即Runnable,然后再提交给一个Excutor执行,Excutor.executor在执行时使用内部的线程池完成操作。Executor在执行时使用内部线程池完成操作;
创建线程池:
Executor executor = Executors.newFixedThreadPool(10); // 创建固定数目线程的线程持;
Executor executor = Executors.newCachedThreadPool(); // 创建一个可缓存的线程池,调用executor将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新的线程并添加到池中;
ExecutorService与生命周期
ExecutorService扩展了Executor并添加了一些生命周期管理的方法。一个Executor的生命周期有三种状态:运行、关闭、终止、Executor创建时处于运行状态、当调用ExecutorServie.shutdown()后,处于关闭状态,isShutdown方法返回true.这时,不应该再想Executor中添加任务,所有已添加的任务执行完毕后,Executor处于终止状态。
学习中参考了http://www.cnblogs.com/end/archive/2012/10/25/2738493.html
http://blog.csdn.net/ac903919/article/details/6967728