在一些特殊的场合,我们可能需要使用异步的IO来大幅提高性能.
如日志信息收集.
而rapid-framework提供的异步IO类,使用生产者/消费者的多线程同步模式及Decorator模式,如同使用正常的IO一样,只需套多一层AsyncWriter/AsyncOutputStream,即可将普通IO转换为异步IO来使用.
打开一个异步IO后,将会在后台开启一个异步的线程来写数据.
异步的Writer使用:
BufferedWriter writer = new BufferedWriter(new AsyncWriter(new FileWriter("c:/debug.log")));
writer.write("xxxxx");
异步的OutputStream使用:
BufferedOutputStream output = new BufferedOutputStream(new AsyncOutputStream(new FileOutputStream("c:/debug.log")));
output.write("foo".getBytes());
在output使用完确保output被close,因为在close时,会强制异步线程将数据全部写入最终的targetOutput. 而调用flush()方法则是空操作,不会写数据.
异步IO使用tip(1):
可以将BufferedWriter/BufferedOutputStream的缓冲区加大,以减少写入次数.
异步IO使用tip(2):
在close异步IO时也放在一个单独的线程中,因为在实际应用场景中,close异步IO可能是十分耗时的操作.
AsyncWriter实现源码:
public class AsyncWriter extends Writer {
private static Log log = LogFactory.getLog(AsyncWriter.class);
private static final int DEFAULT_QUEUE_CAPACITY = 50000;
private final static char[] CLOSED_SIGNEL = new char[0];
private Writer out;
private DataProcessorThread dataProcessor;
private boolean isClosed = false;
private BlockingQueue<char[]> queue ;
private AsyncExceptinHandler asyncExceptinHandler = new DefaultAsyncExceptinHandler();
private static long threadSeqNumber;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
private class DataProcessorThread extends Thread {
private boolean enabled = true;
private boolean hasRuned = false;
DataProcessorThread() {
super("AsyncWriter.DataProcessorThread-"+nextThreadID());
setDaemon(true);
}
public void run() {
hasRuned = true;
while (this.enabled || !queue.isEmpty()) {
char[] buf;
try {
buf = queue.take();
} catch (InterruptedException e) {
// e.printStackTrace();
continue;
}
if(buf == CLOSED_SIGNEL) {
return;
}
try {
out.write(buf);
} catch (IOException e) {
asyncExceptinHandler.handle(e);
}
}
}
}
public AsyncWriter(Writer out) {
this(out,DEFAULT_QUEUE_CAPACITY,Thread.NORM_PRIORITY + 1);
}
public AsyncWriter(Writer out,int queueCapacity) {
this(out,queueCapacity,Thread.NORM_PRIORITY + 1);
}
public AsyncWriter(Writer out,int queueCapacity,int dataProcesserThreadPriority) {
this(out,new ArrayBlockingQueue(queueCapacity),dataProcesserThreadPriority);
}
public AsyncWriter(Writer out,BlockingQueue queue,int dataProcesserThreadPriority) {
if(out == null) throw new NullPointerException();
if(queue == null) throw new NullPointerException();
this.queue = queue;
this.dataProcessor = new DataProcessorThread();
if(dataProcesserThreadPriority != Thread.NORM_PRIORITY) {
this.dataProcessor.setPriority(dataProcesserThreadPriority);
}
this.dataProcessor.start();
this.out = out;
}
public AsyncWriter(Writer out,AsyncExceptinHandler handler) {
this(out);
setAsyncExceptinHandler(handler);
}
public void write(char[] buf, int offset, int length) throws IOException {
synchronized (lock) {
if(isClosed) throw new IOException("already closed");
try {
queue.put(BufferCopyUtils.copyBuffer(buf, offset, length));
} catch (InterruptedException e) {
throw new IOException("AsyncWriter occer error",e);
}
}
}
public void close() throws IOException {
synchronized (lock) {
try {
isClosed = true;
dataProcessor.enabled = false;
if(queue.isEmpty()) {
queue.offer(CLOSED_SIGNEL);
}
try {
dataProcessor.join();
} catch (InterruptedException e) {
//ignore
}
if(!dataProcessor.hasRuned) {
dataProcessor.run();
}
}finally {
out.close();
}
}
}
public void flush() throws IOException {
}
protected void finalize() throws Throwable {
super.finalize();
if(!isClosed) {
log.warn("AsyncWriter not close:"+this);
close();
}
}
public void setAsyncExceptinHandler(AsyncExceptinHandler asyncExceptinHandler) {
if(asyncExceptinHandler == null) throw new NullPointerException();
this.asyncExceptinHandler = asyncExceptinHandler;
}
}
rapid-framework网站:
http://code.google.com/p/rapid-framework
在线javadoc:
http://www.rapid-framework.org.cn/rapid-javadoc-v2.0.x/