| New file | 
|  |  |  | 
|---|
|  |  |  | package com.dy.common.queue; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import org.apache.logging.log4j.LogManager; | 
|---|
|  |  |  | import org.apache.logging.log4j.Logger; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 队列,先进先出 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public class Queue { | 
|---|
|  |  |  | @SuppressWarnings("unfinal") | 
|---|
|  |  |  | private final Logger log = LogManager.getLogger(Queue.class.getName()) ; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private final Object synObj ; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private String queueName ; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private final Node head ; | 
|---|
|  |  |  | private final Node tail ; | 
|---|
|  |  |  | private int size ; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //最大限制,超过这个限制,队列将拒绝push调用,并抛出异常 | 
|---|
|  |  |  | private int maxSize ; | 
|---|
|  |  |  | //警告限制,超过这个限制,队列接收push后,将记录warn日志 | 
|---|
|  |  |  | private int warnSize ;// | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public Queue(String queueName){ | 
|---|
|  |  |  | synObj = new Object() ; | 
|---|
|  |  |  | this.queueName = queueName ; | 
|---|
|  |  |  | if(this.queueName == null){ | 
|---|
|  |  |  | this.queueName = Queue.class.getName() ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.head = new Node() ; | 
|---|
|  |  |  | this.tail = new Node() ; | 
|---|
|  |  |  | this.head.next = this.tail ; | 
|---|
|  |  |  | this.tail.pre = this.head ; | 
|---|
|  |  |  | this.size = 0 ; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | this.warnSize = 1000000 ; | 
|---|
|  |  |  | this.maxSize = Integer.MAX_VALUE ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void setLimit(int warnSize, int maxSize){ | 
|---|
|  |  |  | this.warnSize = warnSize ; | 
|---|
|  |  |  | this.maxSize = maxSize ; | 
|---|
|  |  |  | if(this.warnSize <= 0){ | 
|---|
|  |  |  | this.warnSize = 1 ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(this.warnSize == Integer.MAX_VALUE){ | 
|---|
|  |  |  | this.warnSize = Integer.MAX_VALUE - 1000 ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if(this.maxSize <= 0){ | 
|---|
|  |  |  | this.maxSize = 1 ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 此方法在多线程中执行,同步方式,防止其他线程操作其他方法时不同步 | 
|---|
|  |  |  | * 在队列尾部压入一节点 | 
|---|
|  |  |  | * 在多线程中应用,加同步 | 
|---|
|  |  |  | * @param obj 入列的对象 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @SuppressWarnings("unused") | 
|---|
|  |  |  | public void pushHead(NodeObj obj)throws Exception{ | 
|---|
|  |  |  | synchronized(synObj){ | 
|---|
|  |  |  | if(obj == null){ | 
|---|
|  |  |  | return ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(this.size >= this.maxSize){ | 
|---|
|  |  |  | throw new Exception("队列(" + queueName + ")缓存节点数" + this.size + " 超出最大限制(" + this.maxSize + "),拒绝接收新数据。"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | Node node = new Node(); | 
|---|
|  |  |  | node.obj = obj ; | 
|---|
|  |  |  | node.next = this.head.next ; | 
|---|
|  |  |  | node.pre = this.head ; | 
|---|
|  |  |  | this.head.next.pre = node ; | 
|---|
|  |  |  | this.head.next = node ; | 
|---|
|  |  |  | this.size ++ ; | 
|---|
|  |  |  | if(this.size >= this.warnSize){ | 
|---|
|  |  |  | log.warn("队列(" + queueName + ")缓存节点数 " + this.size + " 超限(" + this.warnSize + ")警告。"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 此方法在多线程中执行,同步方式,防止其他线程操作其他方法时不同步 | 
|---|
|  |  |  | * 在队列尾部压入一节点 | 
|---|
|  |  |  | * 在多线程中应用,加同步 | 
|---|
|  |  |  | * @param obj 入列的对象 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public void pushTail(NodeObj obj)throws Exception{ | 
|---|
|  |  |  | synchronized(synObj){ | 
|---|
|  |  |  | if(obj == null){ | 
|---|
|  |  |  | return ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(this.size >= this.maxSize){ | 
|---|
|  |  |  | throw new Exception("队列(" + queueName + ")缓存节点数" + this.size + " 超出最大限制(" + this.maxSize + "),拒绝接收新数据。"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | Node node = new Node(); | 
|---|
|  |  |  | node.obj = obj ; | 
|---|
|  |  |  | node.next = this.tail ; | 
|---|
|  |  |  | node.pre = this.tail.pre ; | 
|---|
|  |  |  | this.tail.pre.next = node ; | 
|---|
|  |  |  | this.tail.pre = node ; | 
|---|
|  |  |  | this.size ++ ; | 
|---|
|  |  |  | if(this.size >= this.warnSize){ | 
|---|
|  |  |  | log.warn("队列(" + queueName + ")缓存节点数 " + this.size + " 超限(" + this.warnSize + ")警告。"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 此方法在单线程中执行,但可能受调用push的多线程影响,所以也用到了同步 | 
|---|
|  |  |  | * 弹出第一个节点 | 
|---|
|  |  |  | * 在多线程中应用,加同步 | 
|---|
|  |  |  | * @return 出列对象 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public NodeObj pop(){ | 
|---|
|  |  |  | synchronized(synObj){ | 
|---|
|  |  |  | NodeObj obj = null ; | 
|---|
|  |  |  | if(this.size > 0){ | 
|---|
|  |  |  | Node node = this.head.next ; | 
|---|
|  |  |  | if(node != this.tail){ | 
|---|
|  |  |  | obj = node.obj ; | 
|---|
|  |  |  | this.head.next = this.head.next.next ; | 
|---|
|  |  |  | this.head.next.pre = this.head ; | 
|---|
|  |  |  | node.next = null ; | 
|---|
|  |  |  | node.pre = null ; | 
|---|
|  |  |  | this.size -- ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return obj ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 得到第一个节点,但不把节点从队列中清除 | 
|---|
|  |  |  | * @return 第一个对象 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @SuppressWarnings("unused") | 
|---|
|  |  |  | public Node getFirstNode(){ | 
|---|
|  |  |  | Node node = this.head.next ; | 
|---|
|  |  |  | if(node != this.tail){ | 
|---|
|  |  |  | return node ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return null ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 得到最后一个节点,但不把节点从队列中清除 | 
|---|
|  |  |  | * @return 最后一个对象 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @SuppressWarnings("unused") | 
|---|
|  |  |  | public Node getLastNode(){ | 
|---|
|  |  |  | Node node = this.tail.pre ; | 
|---|
|  |  |  | if(node != this.head){ | 
|---|
|  |  |  | return node ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return null ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 清除一个节点 | 
|---|
|  |  |  | * @param node 删除一个节点 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @SuppressWarnings("unused") | 
|---|
|  |  |  | public void remove(Node node){ | 
|---|
|  |  |  | synchronized(synObj){ | 
|---|
|  |  |  | if(node != null && node != this.head && node != this.tail){ | 
|---|
|  |  |  | node.pre.next = node.next ; | 
|---|
|  |  |  | node.next.pre = node.pre ; | 
|---|
|  |  |  | node.next = null ; | 
|---|
|  |  |  | node.pre = null ; | 
|---|
|  |  |  | this.size -- ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 得到队列中有效节点个数 | 
|---|
|  |  |  | * @return 队列内节点数量 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public int size(){ | 
|---|
|  |  |  | return this.size ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|