基于数组阻塞队列 ArrayBlockingQueue 的一个队列工具类

java语言基于ArrayBlockingQueue 开发的一个根据特定前缀和后缀的队列。每天自动循环生成。

  1.定义队列基类 Cookie

  

package com.bytter.util.queue;

import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;

public class Cookie {
    private ArrayBlockingQueue<String> queue;
    private int cursor = 1;
    private Date date = new Date();
    private int maxPoolQueue = 500;
    private int mixPoolQueue = 100;
    
    public Cookie(int maxPoolQueue,int mixPoolQueue,Date date){
        this.maxPoolQueue=maxPoolQueue;
        this.mixPoolQueue=mixPoolQueue;
        this.date=date;
        this.queue = new ArrayBlockingQueue<String>(this.maxPoolQueue,true);
    }
    
    public Cookie(int maxPoolQueue,int mixPoolQueue,Date date, int cursor){
    	this.maxPoolQueue = maxPoolQueue;
    	this.mixPoolQueue = mixPoolQueue;
        this.date=date;
        this.cursor=cursor;
		this.queue = new ArrayBlockingQueue<String>(this.maxPoolQueue,true);
    }
    
    public ArrayBlockingQueue<String> getQueue() {
		return queue;
	}

	public Cookie setQueue(ArrayBlockingQueue<String> queue) {
		this.queue = queue;
		return this;
	}

	public int getCursor() {
		return cursor;
	}

	public Cookie setCursor(int cursor) {
		this.cursor = cursor;
		return this;
	}

	public Date getDate() {
		return date;
	}

	public Cookie setDate(Date date) {
		this.date = date;
		return this;
	}

	public int getMaxPoolQueue() {
		return maxPoolQueue;
	}

	public Cookie setMaxPoolQueue(int maxPoolQueue) {
		this.maxPoolQueue = maxPoolQueue;
		return this;
	}

	public int getMixPoolQueue() {
		return mixPoolQueue;
	}

	public Cookie setMixPoolQueue(int mixPoolQueue) {
		this.mixPoolQueue = mixPoolQueue;
		return this;
	}
	
}

  

  2.QueueUtil 队列工具类,用于获取队列中的值(主要是获取付款的单号==)

package com.bytter.util.queue;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.bytter.framework.persistence.dao.IBaseDAO;
import com.bytter.util.AppContextUtil;
import com.bytter.util.DateUtil;
/**
 * 
 * @author
 * May 6, 2019 10:35:39 AM
 * @version
 */
public class QueueUtil{
	
	private static Logger log = LogManager.getLogger(QueueUtil.class);	
	protected static IBaseDAO baseDao = null;
	private static ConcurrentHashMap<String, Cookie> queueMap = new ConcurrentHashMap<String, Cookie>();
	
	private static class SingletonClassInstance{
        private static final QueueUtil instance=new QueueUtil();
    }
     
    private QueueUtil(){}
     
    public static QueueUtil getInstance(){
        return SingletonClassInstance.instance;
    }
	
	/**
	 * 调用事例: QueueUtil.getInstance().getSequence(SequenceEnum.BIS_EXC)
	 * @param sequenceEnum
	 * @return
	 * @throws InterruptedException
	 */
	@SuppressWarnings("unchecked")
	public String getSequence(SequenceEnum sequenceEnum) throws InterruptedException{
		String value = "";
		String key = sequenceEnum.getTableName()+"_"+sequenceEnum.getFieldName();
		Cookie cookie = queueMap.get(key);
		value  = cookie.getQueue().take();
		String returnValue = sequenceEnum.getPrefix()+DateUtil.dateToStr(sequenceEnum.getDateFormat(), new Date());
		for (int i = 0; i < sequenceEnum.getSequenceLength()-value.length(); i++) {
			returnValue += "0";
		}
		returnValue += value;
		log.info("取出的单号:"+returnValue);
		return returnValue;
	}
	
	public void initQueue() {
		putAllMap();
		Thread thread = new Produce(queueMap);
		thread.setName("QueueUtil_Produce");
		thread.start();
	}

	private static void putAllMap() {
		queueMap.clear();
		int curor = 1;
		log.info("-----开始加载队列 -------");
		for (SequenceEnum sequenceEnum : SequenceEnum.values()){
			String key = sequenceEnum.getTableName()+"_"+sequenceEnum.getFieldName();
			//同一天但是系统重启或者宕机的情况时,游标重置为1.此时需要查询表中最大的值并且置游标值+1
			String sql="SELECT MAX("+sequenceEnum.getFieldName()+") FROM "+sequenceEnum.getTableName()+" WHERE "+sequenceEnum.getFieldName()+" LIKE '"+sequenceEnum.getPrefix()+"%'";
			List list = baseDao.search_sql(null, sql, "", "", null);
			if(list != null && list.size() >0 && list.get(0) != null){
				String no = list.get(0).toString();
				//单号,自增。
				String count = no.substring(no.length()-sequenceEnum.getSequenceLength());
				String date = no.replaceAll(count, "").replaceAll(sequenceEnum.getPrefix(), "");
				/*if(date.equals(DateUtil.dateToStr(sequenceEnum.getDateFormat(), new Date()))){
					curor = Integer.parseInt(count) + 1;
				}*/
			}
			log.info("加载队列 :table=="+sequenceEnum.getTableName()+" field=="+sequenceEnum.getFieldName()+" 游标=="+curor);
			queueMap.put(key, new Cookie(sequenceEnum.getMaxSeqSize(),sequenceEnum.getMinSeqSize(),new Date(),curor));
		}
		log.info("-----队列加载完毕 -------");
	}
	
	static{
		baseDao = AppContextUtil.getBean("baseDao");
		//第一次调用时开启队列
		//initQueue(); 
	}

	
}

  3.生产者线程类

  

package com.bytter.util.queue;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;

import com.bytter.util.DateUtil;

public class Produce extends Thread{
    private ConcurrentHashMap<String, Cookie> queueMap;
    public Produce(ConcurrentHashMap<String, Cookie> queueMap){
        this.queueMap=queueMap;
    }
    public void run(){
    	ArrayBlockingQueue<String> queue;
    	int mixSize;
    	int curor;
    	Cookie cookie;
    	Date date;
    	Map.Entry<String,Cookie> entry;
    	Iterator<Map.Entry<String,Cookie>> iteratorMap;
    	while (true) {
    		iteratorMap = queueMap.entrySet().iterator();
            while (iteratorMap.hasNext()){
                entry = iteratorMap.next();
                cookie = entry.getValue();
    			queue = cookie.getQueue();
    			mixSize = cookie.getMixPoolQueue();
    			curor = cookie.getCursor();
    			date = cookie.getDate();
    			//新的一天,游标开始重置
    			if(!DateUtil.dateToStr("yyyy-MM-dd", new Date()).equals(DateUtil.dateToStr("yyyy-MM-dd", date))){
    				curor = 1;
    				queue.clear();
    				date = new Date();
    				System.out.println("重置游标时间===="+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    			}
    			
    			//offer 在填满后返回false
    			if(queue.size() < mixSize){
    				while (queue.offer(curor + "")) {
    					curor++;
    				}
    			}
    			cookie.setQueue(queue).setCursor(curor).setDate(date);
    			queueMap.put(entry.getKey(),cookie);
            }
		}
    }
}

  4.自定义的生成单号的规则枚举类

  

package com.bytter.util.queue;
public enum SequenceEnum{
		/**
		 * 付款指令编码 yyMMdd000001
		 * @return 
		 */
		BIS_EXC("",6, "BIS_EXC", "VOUCHER_NO", "yyMMdd",500,100),
		/**
		 * 付款单号
		 * @return 
		 */
		PAYMENT_BILL_NO("P",7, "T_BIS_PAYMENT_INFO", "BILL_CODE", "yyMMddHHmmss",500,100),
		
		;
		
		
		/**
		 * 流水号前缀
		 */
		private String prefix;

		/**
		 * 流水号数字部分长度
		 */
		private Integer sequenceLength;
		/**
		 * 业务表名
		 */
		private String tableName;
		/**
		 * 业务表中的字段名
		 */
		private String fieldName;
		/**
		 * 日期格式化模板
		 */
		private String dateFormat;
		
		/**
		 * 队列最大的长度
		 */
		private int maxSeqSize;
		/**
		 * 队列最小长度
		 */
		private int minSeqSize;
		
		
		/**
		 * @param prefix           流水号前缀
		 * @param sequenceLength   流水号自增长长度
		 * @param tableName        表名
		 * @param fieldName        字段名
		 * @param dateFormat       日期格式化模板
		 */
		SequenceEnum(String prefix, Integer sequenceLength, String tableName, String fieldName,String dateFormat,int maxSeqSize,int minSeqSize) {
			this.prefix = prefix;
			this.sequenceLength = sequenceLength;
			this.tableName = tableName;
			this.fieldName = fieldName;
			this.dateFormat = dateFormat;
			this.maxSeqSize = maxSeqSize;
			this.minSeqSize = minSeqSize;
		}
		
		/**
		 * @param prefix           流水号前缀
		 * @param sequenceLength   流水号自增长长度
		 * @param tableName        表名
		 * @param fieldName        字段名
		 * @param dateFormat       日期格式化模板
		 */
		SequenceEnum(Integer sequenceLength, String tableName, String fieldName,String dateFormat) {
			this.sequenceLength = sequenceLength;
			this.tableName = tableName;
			this.fieldName = fieldName;
			this.dateFormat = dateFormat;
		}
		
		public String getPrefix() {
			return prefix;
		}
		public void setPrefix(String prefix) {
			this.prefix = prefix;
		}
		public Integer getSequenceLength() {
			return sequenceLength;
		}
		public void setSequenceLength(Integer sequenceLength) {
			this.sequenceLength = sequenceLength;
		}
		public String getTableName() {
			return tableName;
		}
		public void setTableName(String tableName) {
			this.tableName = tableName;
		}
		public String getFieldName() {
			return fieldName;
		}
		public void setFieldName(String fieldName) {
			this.fieldName = fieldName;
		}

		public String getDateFormat() {
			return dateFormat;
		}

		public void setDateFormat(String dateFormat) {
			this.dateFormat = dateFormat;
		}

		public int getMaxSeqSize() {
			return maxSeqSize;
		}

		public void setMaxSeqSize(int maxSeqSize) {
			this.maxSeqSize = maxSeqSize;
		}

		public int getMinSeqSize() {
			return minSeqSize;
		}

		public void setMinSeqSize(int minSeqSize) {
			this.minSeqSize = minSeqSize;
		}

	}

  5.测试相关类

    1> 消费者线程

    

package com.bytter.util.queue;

public class 	 implements Runnable{
	
	
	
    public void run(){
		try {
			for (int i = 0; i < 200; i++) {
				Thread.sleep(Long.valueOf((long) (Math.random()*10*300)));
//				System.out.println(Thread.currentThread().getName());
				System.out.println(Thread.currentThread().getName()+"==="+SequenceUtilTest.getInstance().getSequence(SequenceEnum.BIS_EXC));
			}
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
    }
}

    2>测试main 方法

package com.bytter.util.queue;

public class tests {

	
	public static void main(String[] args) throws InterruptedException {
		new Thread(new Consume()).start();
		new Thread(new Consume()).start();
		new Thread(new Consume()).start();
		new Thread(new Consume()).start();
		new Thread(new Consume()).start();
//		new Thread(new Consume()).start();
//		new Thread(new Consume()).start();
//		new Thread(new Consume()).start();
//		new Thread(new Consume()).start();
//		new Thread(new Consume()).start();
	}
}

  

posted @ 2019-07-31 11:05  _万古如长夜  阅读(400)  评论(0编辑  收藏  举报