试试看jdk 1.7里面的异步通道吧,java.nio.channels.AsynchronousXXX的几个类。
许多操作系统自身就支持AIO,因此可以jvm可以把操作系统的异步通讯封装后直接提供给java程序使用。使用操作系统的aio, java程序中可以不用再搞多线程了。
以前写的一个EchoServer的例子,在Win7 64bit上开1000个端口还挺正常的,占用物理内存30M,虚拟内存60M左右。
package org.lex.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import javax.swing.JOptionPane;
import org.apache.log4j.Logger;
public class ServerSocketTest {
public static void main(String[] args) {
new ServerSocketTest().run();
JOptionPane.showMessageDialog(null, "点“确定”关闭服务器");
}
private Logger log = Logger.getLogger(getClass());
public void run() {
int start = 40000;
int end = 41000;
for (int port = start; port < end; port++) {
try {
this.listen(port);
} catch (Exception e) {
log.error("listen failed on port " + port);
}
}
}
private void listen(int port) throws IOException {
final AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open().bind(
new InetSocketAddress(port));
log.info("open & bing on port " + port);
serverSocketChannel.accept(null, new EchoHandler());
}
/**
* 回显客户端的输出
*/
private static final class EchoHandler implements CompletionHandler {
private Logger log = Logger.getLogger(EchoHandler.class);
@Override
public void completed(AsynchronousSocketChannel result, Void attachment) {
ByteBuffer buf = ByteBuffer.allocate(256);
try {
int readLength = 0;
SocketAddress clientAddr = result.getRemoteAddress();
log.info("accept a client: " + clientAddr);
while ((readLength = result.read(buf).get()) > 0) {
buf.flip();
log.info("[" + clientAddr + "] read " + readLength + " bytes");
int writeLength = result.write(buf).get();
log.info("[" + clientAddr + "] write " + writeLength + " bytes");
buf.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Void attachment) {
log.error("handle client failed", exc);
}
}
}