我在win7 下用aio做了AIO线程测试,大致步骤如下:
- 使用AsynchronousServerSocketChannel监听6025端口
- 为第一步设置的channel设定一个大小为4的AsynchronousChannelGroup
-
为CompletionHandler实现了一个匿名内部类,并且在completed方法中强制当前线程sleep20秒。
-
然后我开了两个command line窗口,各尝试了一次telnet 6025端口:'telnet localhost 6025'
在我预想中,这两个telnet应该会直接返回,并且在后台打印出相关内容,两次telnet调用应该不会阻塞。
但事实情况是第二次调用会等到第一次调用20s sleep时间过去之后再处理第二条。这是console log,注意一下两次打印的时间差了20s:
-
the main thread is 1
Listening on localhost:6025
Channel Provider : sun.nio.ch.WindowsAsynchronousChannelProvider@17f17060
waiting....
current thread is 10
sleep the thread 10,current time is Fri Aug 04 08:48:21 CST 2017
thread 10 has wake up!!!
waiting....
current thread is 11
sleep the thread 11,current time is Fri Aug 04 08:48:41 CST 2017
thread 11 has wake up!!!
这难道就是传说中的阻塞?虽然我知道在completed方法中要是有长时间未响应的处理,很容易hang掉系统,尤其是fixthreadpool,但前提是线程池撑爆了!但我的线程池有4个,而且并未用满,为什么还会阻塞呢?
下面是我的代码:
public class AIOEchoServer {
private AsynchronousServerSocketChannel server;
public static void main(String[] args) throws Exception {
System.out.println("the main thread is "+Thread.currentThread().getId());
AIOEchoServer aioServer = new AIOEchoServer();
aioServer.init("localhost", 6025);
}
private void init(String host, int port) throws IOException, Exception {
AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(4));
server = AsynchronousServerSocketChannel.open(group);
server.setOption(StandardSocketOptions.SO_REUSEADDR, true);
server.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);
server.bind(new InetSocketAddress(host, port));
System.out.println("Listening on " + host + ":" + port);
System.out.println("Channel Provider : " + server.provider());
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
final ByteBuffer buffer = ByteBuffer.allocate(1024);
@Override
public void completed(AsynchronousSocketChannel result, Object attachment) {
System.out.println("waiting....");
buffer.clear();
System.out.println("current thread is "+Thread.currentThread().getId());
try {
System.out.println("sleep the thread "+Thread.currentThread().getId()+",current time is "+new Date());
Thread.currentThread().sleep(20000l);
System.out.println("thread "+Thread.currentThread().getId()+" has wake up!!!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
result.close();
server.accept(null, this);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void failed(Throwable exc, Object attachment) {
System.out.print("Server failed...." + exc.getCause());
}
});
group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
}
}