Java文件Queue实现
来源:互联网 发布:三流程序员写ui 编辑:程序博客网 时间:2024/06/06 05:35
这是一个新的系列,将会记录在工作之外写的一些小的程序,而且是有一定难度并且实用的小代码,相信会给自己和给读者一些收获。
这个系列的原因是有的时候回想自己的工作历程经常想不起曾经实现过哪些有意思的东西,总结提炼过哪些模型,这个系列将会记录这一切。
在前段时间的工作中曾经有个需求是要对一个内存中的Queue做持久化。组内的大牛使用了文件完成了一个FileBasedQueue,很有意思,把代码简化和重写了后下放出来:
实现要点:
1.使用了NIO、FileChannel、MappedByteBuffer来加快读写文件的速度
2.一次创建一个128M的文件Page,如果不够用再开辟下一个文件Page
3.单独使用一个Index文件记录当前读和写分别是在哪个文件Page中
4.使用一个Type位标记文件中对象的状态:EMPTY、FULL、ROTATE
5.用sun的cleaner来完成MappedByteBuffer的unmap
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.Closeable;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.RandomAccessFile;import java.io.Serializable;import java.nio.ByteBuffer;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import com.sun.corba.se.impl.ior.WireObjectKeyTemplate;import sun.nio.ch.DirectBuffer;import static java.nio.channels.FileChannel.MapMode.READ_WRITE;public class FileQueue<T extends Serializable> {public static final int PAGE_SIZE = 128 * 1024 * 1024;public static final int SIZE_OF_INT = 4;public static String FILE_NAME = "data";public static String FILE_SUFFIX = ".dat";public static String INDEX_NAME = "data.inx";public String fileDir;private RandomAccessFile readFile;private RandomAccessFile writeFile;private RandomAccessFile indexFile;private FileChannel readChannel;private FileChannel writeChannel;private FileChannel indexChannel;private MappedByteBuffer readMbb;private MappedByteBuffer writeMbb;private MappedByteBuffer indexMbb;private static final int INDEX_SIZE = SIZE_OF_INT + SIZE_OF_INT;private static final int HEADER_SIZE = SIZE_OF_INT+ SIZE_OF_INT;private static final int ENDER_SIZE = HEADER_SIZE;private ByteBuffer headerBb = ByteBuffer.allocate(HEADER_SIZE);private int readIndexFile;private int writeIndexFile;private enum ITEM_TYPE {EMPTY, FILL, ROTATE}public FileQueue(String fileDir) throws IOException {if (fileDir == null || fileDir.trim().length() == 0) {throw new IllegalArgumentException("filename illegal");}if (!fileDir.endsWith("/")) {fileDir += File.separator;}File dir = new File(fileDir);if (!dir.exists()) {dir.mkdirs();}this.fileDir = fileDir;indexFile = new RandomAccessFile(fileDir + INDEX_NAME, "rw");indexChannel = indexFile.getChannel();indexMbb = indexChannel.map(READ_WRITE, 0, INDEX_SIZE);readIndexFile = indexMbb.getInt();writeIndexFile = indexMbb.getInt();readFile = new RandomAccessFile(fileDir + FILE_NAME + readIndexFile + FILE_SUFFIX, "rw");readChannel = readFile.getChannel();writeFile = new RandomAccessFile(fileDir + FILE_NAME + writeIndexFile + FILE_SUFFIX, "rw");writeChannel = writeFile.getChannel();readMbb = readChannel.map(READ_WRITE, 0, PAGE_SIZE);writeMbb = writeChannel.map(READ_WRITE, 0, PAGE_SIZE);initWriteMbb();initReadMbb();}private void initReadMbb(){int currentPos = readMbb.position();int type = readMbb.getInt();int length = readMbb.getInt();while(type == ITEM_TYPE.EMPTY.ordinal() && length > 0){readMbb.position(currentPos + HEADER_SIZE + length);currentPos = readMbb.position();type = readMbb.getInt();length = readMbb.getInt();}readMbb.position(currentPos);}private void initWriteMbb(){int currentPos = writeMbb.position();int type = writeMbb.getInt();int length = writeMbb.getInt();while(length > 0){writeMbb.position(currentPos + HEADER_SIZE + length);currentPos = writeMbb.position();type = writeMbb.getInt();length = writeMbb.getInt();}writeMbb.position(currentPos);}public synchronized void product(T item) throws Exception {if (item == null) {throw new IllegalArgumentException("item is null");}byte[] contents = toBytes(item);int length = contents.length;int writePos = writeMbb.position();// if reach the button of the filequeueif (writePos + length + ENDER_SIZE + HEADER_SIZE >= PAGE_SIZE) {writeIndexFile += 1;writeMbb.putInt(ITEM_TYPE.ROTATE.ordinal());writeMbb.force();unmap(writeMbb);closeResource(writeChannel);closeResource(writeFile);writeFile = new RandomAccessFile(fileDir + FILE_NAME + writeIndexFile + FILE_SUFFIX, "rw");writeChannel = writeFile.getChannel();writeMbb = writeChannel.map(READ_WRITE, 0, PAGE_SIZE);indexMbb.putInt(Integer.SIZE, writeIndexFile);}headerBb.clear();headerBb.putInt(ITEM_TYPE.FILL.ordinal());headerBb.putInt(length);headerBb.flip();writeMbb.put(headerBb);writeMbb.put(contents);}private byte[] toBytes(T item) throws IOException {ByteArrayOutputStream baos = null;ObjectOutputStream oos = null;try {baos = new ByteArrayOutputStream();oos = new ObjectOutputStream(baos);oos.writeObject((Object) item);oos.flush();return baos.toByteArray();} finally {closeResource(baos);closeResource(oos);}}public synchronized T comsume() throws Exception {int readPos = readMbb.position();int type = readMbb.getInt();int length = readMbb.getInt();if(type == ITEM_TYPE.ROTATE.ordinal()){readIndexFile += 1;readMbb.putInt(ITEM_TYPE.ROTATE.ordinal());readMbb.force();unmap(readMbb);closeResource(readChannel);closeResource(readFile);readFile = new RandomAccessFile(fileDir + FILE_NAME + readIndexFile + FILE_SUFFIX, "rw");readChannel = readFile.getChannel();readMbb = readChannel.map(READ_WRITE, 0, PAGE_SIZE);indexMbb.putInt(0, readIndexFile);type = readMbb.getInt();length = readMbb.getInt();}if(type == ITEM_TYPE.EMPTY.ordinal() || length <= 0){readMbb.position(readPos);return null;}byte[] contents = new byte[length];readMbb.get(contents);readMbb.putInt(readPos, ITEM_TYPE.EMPTY.ordinal());T object = toObject(contents);return object;}private T toObject(byte[] content) throws IOException,ClassNotFoundException {ByteArrayInputStream bais = null;ObjectInputStream ois = null;try {bais = new ByteArrayInputStream(content);ois = new ObjectInputStream(bais);return (T) ois.readObject();} finally {closeResource(bais);closeResource(ois);}}private void closeResource(Closeable c) throws IOException {if (c != null) {c.close();}}private static void unmap(MappedByteBuffer buffer){if (buffer == null) return; sun.misc.Cleaner cleaner = ((DirectBuffer) buffer).cleaner(); if (cleaner != null) { cleaner.clean(); }}public void shutdown() throws IOException {if (writeMbb != null) {writeMbb.force();unmap(writeMbb);}if (readMbb != null) {readMbb.force();unmap(readMbb);}if (indexMbb != null) {indexMbb.force();unmap(indexMbb);}closeResource(readChannel);closeResource(readFile);closeResource(writeChannel);closeResource(writeFile);closeResource(indexChannel);closeResource(indexFile);}}
- Java文件Queue实现
- java Queue容器实现
- java Queue容器实现
- Java中Queue类实现
- Java如何实现queue队列?
- Queue(java)实现先进先出
- uva 133 - The Dole Queue|java实现
- Java中使用LinkedList实现Queue
- 基于双链表 实现Java Queue队列
- 使用Java实现简单的队列(queue)
- Java实现栈Stack和队列Queue
- 用两个stack实现Queue(java)
- Java实现一个简单的队列---Queue
- Queue-实现
- Queue实现
- Queue实现
- Queue实现
- Queue 实现
- Linux 常用命令——ls
- 使用javascript及servlet实现客户端和服务器端的表单验证
- 浅谈UML之交互图
- 分享Unity工具十天创建iPad游戏的经验
- sscanf用法详解
- Java文件Queue实现
- CFile Class
- ffmpeg 从mp4上提取H264的nalu
- 开发商可借手机游戏反哺传统游戏项目
- 了解面向对象技术
- Android使用自定义对话框报错:The specified child already has a parent. You must call removeView() on the...
- Objective-c中的内存管理的黄金法则,OC中最重要的部分
- 解析手机游戏制胜10大关键因素
- windows 远程图形化控制 suse 与ubuntu