- 接口定义
public interface Queue {
public boolean offer(Object obj);
public Object poll();
public Object poll(long wait);
public int size();public boolean isEmpty();
public void addQueueListener(QueueListener listener);
}
- 实现1
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;
import java.util.Vector;public class LinkedQueue implements Queue {
private static final int DEFAULT_CAPACITY = 1000;
private LinkedList list;
private int capacity;
private Object lock = new Object();
public LinkedQueue() {
this(DEFAULT_CAPACITY);
}public LinkedQueue(int capacity) {
this.capacity = capacity;
this.list = new LinkedList();
}public void addQueueListener(QueueListener listener) {
}
public boolean isEmpty() {
synchronized (lock) {
return list.isEmpty();
}
}public boolean offer(Object obj) {
synchronized (lock) {
if (list.size() >= this.capacity) {
return false;
}
list.addLast(obj);
lock.notifyAll();
return true;
}
}public Object poll() {
return poll(0);
}public Object poll(long wait) {
synchronized (lock) {
try {
if (list.isEmpty()) {
lock.wait(wait);
}
} catch (InterruptedException e) {
return null;
}
if (list.isEmpty()) {
return null;
} else {
return list.removeFirst();
}
}}
public int size() {
synchronized (lock) {
return list.size();
}
}public int getCapacity() {
return capacity;
}public void clear() {
synchronized (lock) {
list.clear();
}
}private Vector vector() {
Vector v = new Vector(list);
list.clear();
return v;
}public int saveToDisk(File f) {
synchronized (lock) {
if (f.isDirectory())
return 0;
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(f, true));
Vector v = vector();
oos.writeObject(v);
oos.flush();
return v.size();
} catch (IOException e) {
e.printStackTrace();
return 0;
} finally {
try {
if (oos != null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}}
}public int revertFromDisk(File f) {
synchronized (lock) {
if (!f.exists() || !f.canRead())
return 0;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(f));
Object obj = ois.readObject();
if (obj != null) {
Vector v = (Vector) obj;
if(list.addAll(v))
return v.size();
}
return 0;
} catch (FileNotFoundException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return 0;
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
}
}
if (f != null) {
f.delete();
}
}
}
}
}
- 实现2
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class PersistableQueue implements Queue {
private LinkedQueue queue;
private static final int DEFAULT_MAX_LENGTH = 10000;
/**
* 队列名称
*/
private String name;/**
* 持久目录
*/
private String directory;/**
* 持久文件计数器
*/
private int fileCount;/**
* 在磁盘上的队列长度
*/
private int diskSize;/**
* 当前文件编号
*/
private int currentFileNum;/**
* 最后文件编号
*/
private int lastFileNum;private Object lock = new Object();
public PersistableQueue(String directory, String name) {
this.directory = directory;
this.name = name;
this.queue = new LinkedQueue(DEFAULT_MAX_LENGTH);
restoreIndex();
}public void addQueueListener(QueueListener listener) {
}public boolean isEmpty() {
synchronized (lock) {
return queue.isEmpty() && diskSize == 0;
}
}public boolean offer(Object obj) {
boolean success = queue.offer(obj);
if (!success) {
synchronized (lock) {
memoryToDisk();
}
return queue.offer(obj);
}
return success;
}public Object poll() {
return poll(0);
}public Object poll(long wait) {
if (queue.isEmpty()) {
synchronized (lock) {
this.diskToMemory();
}
}
return queue.poll(wait);
}public int size() {
synchronized (lock) {
return queue.size() + diskSize;
}}
public void close() {
synchronized (lock) {
memoryToDisk();
}
}/**
* 内存到磁盘
*
*/
private void memoryToDisk() {
lastFileNum++;
fileCount++;
File file = new File(this.directory + File.separator + name + "_"
+ lastFileNum + ".data");
int num = queue.saveToDisk(file);
// Console.info("save:"+num);
diskSize = diskSize + num;
try {
updateIndex();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}/**
* 加载磁盘缓冲到内存
*
*/
private void diskToMemory() {
File file = null;
try {
do {
if (currentFileNum < lastFileNum && fileCount > 0) {
fileCount--;
currentFileNum++;
file = new File(this.directory + File.separator + name
+ "_" + currentFileNum + ".data");
} else {
break;
}
} while (!file.exists());
if (file == null || !file.exists()) {
// updateIndex();
return;
}
int num = queue.revertFromDisk(file);
/*if (num > 10000)
Console.info("revert:" + num);*/
diskSize = diskSize - num;
updateIndex();
} catch (FileNotFoundException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}private void updateIndex() throws FileNotFoundException, IOException {
if (diskSize <= 0) {
fileCount = 0;
lastFileNum = 0;
currentFileNum = 0;
diskSize = 0;
}
FileWriter fw = null;
try {
File file = new File(this.directory + File.separator + name
+ ".inidex");
if (file.exists())
file.delete();
fw = new FileWriter(file, true);
fw.write("CurrentFileNum:" + currentFileNum + "/n");
fw.write("LastFileNum:" + lastFileNum + "/n");
fw.write("FileCount:" + fileCount + "/n");
fw.write("DiskSize:" + diskSize + "/n");
} finally {
if (fw != null)
fw.close();
}
}private void restoreIndex() {
File file = new File(this.directory + File.separator + name + ".inidex");
if (!file.exists())
return;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
this.currentFileNum = Integer
.parseInt(br.readLine().split("[:]")[1]);
this.lastFileNum = Integer.parseInt(br.readLine().split("[:]")[1]);
this.fileCount = Integer.parseInt(br.readLine().split("[:]")[1]);
this.diskSize = Integer.parseInt(br.readLine().split("[:]")[1]);
} catch (FileNotFoundException e) {
throw new IllegalStateException(e);
} catch (IOException e) {
throw new IllegalStateException(e);
} finally {
try {
if (br != null)
br.close();
} catch (IOException e) {
}
}
}}