考虑到效率问题,没有用list或对象数组实现队列。而是用一个字节数组。消息作为字节流存取,消息的具体格式完全决定于应用。程序运行时没有任何内存分配和释放的操作。提高了存取速度,内存的使用效率和系统的稳定性。
由于有多个线程同时读写队列,所以队列的读写操作要线程同步。
//queue.java
package threadplus;
public class Queue extends Object{
private int msgCount; //the current number of msg in the queue
private int queHead; // the first msg address in the queue
private int queTail; // the first available byte
private int queSize;
private int freeSize;
private int usedPercent;
byte[] queue;
public Queue()
{
queSize=2048; //default size
msgCount = 0;
queHead = queTail=0;
freeSize=queSize;
queue = new byte[queSize];
}
///
///
public Queue(int queueSize)
{
queSize = queueSize;
msgCount = 0;
queHead = queTail=0;
freeSize=queSize;
queue = new byte[queSize];
}
public synchronized int getMessage(byte[] buf, int bufSize, int timeout)
{
int msgSize=0;
int left;
int firstByte,secondByte,thirdByte,fourthByte;
if(msgCount==0)
{
//System.out.println("No message.... ");
try
{
wait(timeout);
if(msgCount==0)
return 0;
}
catch(Exception e)
{
System.err.println("Exception: " + e);
e.printStackTrace();
return 0;
}
}
firstByte = (0x000000FF & ((int)queue[queHead++]));
if(queHead==queSize)
queHead=0;
secondByte =(0x000000FF & ((int)queue[queHead++]));
if(queHead==queSize)
queHead=0;
thirdByte = (0x000000FF & ((int)queue[queHead++]));
if(queHead==queSize)
queHead=0;
fourthByte =(0x000000FF & ((int)queue[queHead++]));
if(queHead==queSize)
queHead=0;
msgSize = firstByte << 24 | secondByte << 16 |
thirdByte << 8 | fourthByte;
if(msgSize==0)
return 0;
if(msgSize>bufSize)
return -1;
left=queue.length-queHead;
if(msgSize<=left)
{
System.arraycopy(queue, queHead, buf, 0, msgSize);
queHead+=msgSize;
if(queHead==queSize)
queHead=0;
}
else
{
System.arraycopy(queue, queHead, buf, 0, left);
System.arraycopy(queue, 0, buf, left, msgSize-left);
queHead=msgSize-left-1;
}
msgCount--;
//System.out.println("Get msg:head"+queHead+",tail:"+queTail+",msgCount:"+msgCount+",msgSize:"+msgSize);
return msgSize;
}
public synchronized int putMessage(byte[] msg, int msgSize)
{
int free=0;
int left;
if(queTail>=queHead)
{
free=queSize-(queTail-queHead);
}
else
{
free=queHead-queTail;
}
if(free<msgSize+4)
{
return -1;
}
queue[queTail++]=(byte)((msgSize & 0xFF000000L)>>24);
if(queTail==queSize)
queTail=0;
queue[queTail++]=(byte)((msgSize & 0x00FF0000L)>>16);
if(queTail==queSize)
queTail=0;
queue[queTail++]=(byte)((msgSize & 0x0000FF00L)>>8);
if(queTail==queSize)
queTail=0;
queue[queTail++]=(byte)(msgSize & 0x000000FFL);
if(queTail==queSize)
queTail=0;
left=queue.length-queTail;
if(msgSize<=left)
{
System.arraycopy(msg, 0, queue, queTail, msgSize);
queTail+=msgSize;
if(queTail==queSize)
queTail=0;
}
else
{
System.arraycopy(msg, 0,queue, queTail, left);
System.arraycopy(msg, left, queue, 0, msgSize-left);
queTail=msgSize-left-1;
}
msgCount++;
notify();
//System.out.println("Put msg:head"+queHead+",tail:"+queTail+",msgCount:"+msgCount+",msgSize:"+msgSize);
return 0;
}
///
public synchronized int getMsgCount()
{
return msgCount;
}
///
public synchronized int getFreeSize()
{
return freeSize;
}
///
public synchronized int getUsedPercent()
{
return usedPercent;
}
public void purgeQue()
{
msgCount = 0;
queHead = 0;
freeSize=queSize;
return;
}
public int getQueSize()
{
return queSize;
}
}