持久化Queue


/**
 * 队列接口
 *
 * @author yourname (mailto:[email protected])
 */
public interface IQueue<E> {
	
	//入队
	void offer(E o);
	
	//出队
	E poll();	

	// 启动
	void start();
	
	// 停止
	void stop();
}

/**
 * 持久化队列
 *
 * @author yourname (mailto:[email protected])
 */
public class PersistenceQueue<E> implements IQueue<E>{
	
	private IPersistence persistence;
	
	//读块缓存
	private LinkedList<E> dataCacheForRead;
	
	//写块缓存
	private ArrayList<E> dataCacheForWrite;
	
	//容量
	private int capacity;
	
	public PersistenceQueue(int capacity, IPersistence persistence) {
		if (capacity <= 0) {
			throw new IllegalArgumentException("Illegal Capacity: "+ capacity);
		}
            
		dataCacheForRead = new LinkedList<E>();
		dataCacheForWrite = new ArrayList<E>(capacity);
		this.capacity = capacity;
		this.persistence = persistence;
	}
	
	//入队
	@SuppressWarnings("unchecked")
	public void offer(E o) {
		if (!isStarted()) {
			throw new IllegalStateException("Queue has not yet started!");
		}
		synchronized(dataCacheForWrite) {
			//如果写满
			if (dataCacheForWrite.size() >= capacity) {			
					persistence.persistent(dataCacheForWrite);
					dataCacheForWrite.clear();
				
			}
			dataCacheForWrite.add(o);
		}
	}
	
	//出队
	@SuppressWarnings("unchecked")
	public E poll() {
		if (!isStarted()) {
			throw new IllegalStateException("Queue has not yet started!");
		}
		synchronized(dataCacheForRead) {
			//如果为空
			if (dataCacheForRead.isEmpty()) {
				//持久化如果为空
				if (persistence.isEmpty()) {
					//直接从写缓存块中读出
					synchronized(dataCacheForWrite) {
						dataCacheForRead.addAll(dataCacheForWrite);
						dataCacheForWrite.clear();
					}
				} else {
					dataCacheForRead.addAll(persistence.load(capacity));
				}
			}
			return dataCacheForRead.poll();
		}
	}

	
	public void start() {
		persistence.start();
		if (persistence.isEmpty()) {
			return;
		}
		dataCacheForRead.addAll(persistence.load(capacity));		
	}

	
	public void stop() {
		if (dataCacheForWrite.isEmpty()) {
			return;
		}
		persistence.persistent(dataCacheForWrite);
		dataCacheForWrite.clear();	
		persistence.stop();	
	}
}

/**
 * 持久化接口
 *
 * @author yourname (mailto:[email protected])
 */
public interface IPersistence<E> {
	
	//是否为空
	boolean isEmpty();
	
	//持久化
	void persistent(List<E> list);
	
	//加载
	List<E> load(int length);

	// 启动
	void start();
	
	// 停止
	void stop();
}

/**
 * 目录方式的持久化
 *
 * @author yourname (mailto:[email protected])
 */
public class DirPersistence<E> implements IPersistence<E> {
	
	private static final ILogger log = DebugLoggerFactory.getLogger(DirPersistence.class);
	
	private static final String FILE_QUEUE_NAME = "queue.meta";
	
	private File dir = null;
	
	private File queueMetaFile = null;
	
	private ConcurrentLinkedQueue<File> fileQueue;
	
	private IDataMarshaller marshaler = null;
	
	public DirPersistence(File dir) {
		if (dir == null) {
			throw new IllegalArgumentException("Dir is null!");
		}
		if (!dir.exists()) {
			log.warn("Path[{0}] is not existed!", new Object[]{dir.getAbsolutePath()});
			dir.mkdirs();
		}
		if (dir.isFile()) {
			throw new IllegalArgumentException("Path'" + dir.getAbsolutePath() + "' is not dir!");
		}
		this.dir = dir;
		this.queueMetaFile = new File(dir, FILE_QUEUE_NAME);
		if (!queueMetaFile.exists()) {
			try {
				queueMetaFile.createNewFile();
			} catch (IOException e) {
				throw new IllegalArgumentException("Path'" + queueMetaFile.getAbsolutePath() + "' can not create!");
			}
		}
		marshaler = DataMarshallerFactory.getDataMarshaller();		
	}
	
	public void start() {
		if (queueMetaFile.length() <= 0) {
			fileQueue = new ConcurrentLinkedQueue<File>();
			return;
		}
		FileInputStream in = null;
		try {			
			in = new FileInputStream(queueMetaFile);
			fileQueue = (ConcurrentLinkedQueue<File>) marshaler.unmarshal(in, null);
		} catch (Exception e) {
			log.error("File[{0}] load error!", new Object[]{queueMetaFile.getAbsolutePath()}, e);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException ignore) {
					log.debug(ignore);
				}
			}				
		}
		
	}
	
	public void stop() {
		FileOutputStream out = null;
		try {			
			out = new FileOutputStream(queueMetaFile);
			marshaler.marshal(fileQueue, out, null);
			out.flush();
		} catch (Exception e) {
			log.error("File[{0}] persistent error!", new Object[]{queueMetaFile.getAbsolutePath()}, e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException ignore) {
					log.debug(ignore);
				}
			}
		}
	}
	
	public boolean isEmpty() {
		return fileQueue == null || fileQueue.isEmpty();
	}
	
	@SuppressWarnings("unchecked")
	//注意:length参数此时无效,即使Queue长度调整了,系统在运行一段时间后,长度会自动一致。(读块、写块和一个文件。)
	public List<E> load(int length) {
		List<E> resultList = new ArrayList<E>();
		if (!isEmpty()) {
			File file = fileQueue.poll();
			if (file.exists()) {
				FileInputStream in = null;
				boolean isNeedDelete = true;
				try {
					
					in = new FileInputStream(file);
					resultList = (List<E>) marshaler.unmarshal(in, null);
				} catch (Exception e) {
					isNeedDelete = false;
					log.error("File[{0}] load error!", new Object[]{file.getAbsolutePath()}, e);
				} finally {
					if (in != null) {
						try {
							in.close();
						} catch (IOException ignore) {
							log.debug(ignore);
						}
					}				
				}
				if (isNeedDelete) {
					file.delete();		
				}	
			} else {
				log.warn("PersistentFile[{0}] is not existed!", new Object[]{file.getAbsolutePath()});
			}
		}
		return resultList;
	}
	
	public void persistent(List<E> list) {
		if (list == null) {
			return;
		}
		String fileName = "queue_" + System.currentTimeMillis() + ".queue";
		File file = new File(dir, fileName);
		
		FileOutputStream out = null;
		try {
			file.createNewFile();
			out = new FileOutputStream(file);
			marshaler.marshal(list, out, null);
			out.flush();
			this.fileQueue.offer(file);
			//文件写入时异步方式,需要等待20ms,否则load时会报错
			Thread.sleep(20);
		} catch (Exception e) {
			log.error("File[{0}] persistent error!", new Object[]{file.getAbsolutePath()}, e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException ignore) {
					log.debug(ignore);
				}
			}
		}
	}
}

你可能感兴趣的:(code)