Java AIO AsynchronousServerSocketChannel阻塞问题

我在win7 下用aio做了AIO线程测试,大致步骤如下:

  1. 使用AsynchronousServerSocketChannel监听6025端口
  2. 为第一步设置的channel设定一个大小为4的AsynchronousChannelGroup
  3. 为CompletionHandler实现了一个匿名内部类,并且在completed方法中强制当前线程sleep20秒。

    1. 然后我开了两个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);        

    }  
} 

在CompletionHandler的complete方法中,要继续accept,否则他就只处理一个,aio是要每接收一个重新accept一次的。

哇,一个月后才看到。我还是说一下吧,一楼已经说了。
accept()函数只处理一个连接,你 第一次调用server.accept(null, new CompletionHandler())的时候接受了第一个连接对吧?
然后程序跑到completed()函数执行try块的方法,这时线程睡眠中,然后又有一个请求来了,线程还在睡眠,所以第二个请求现在还不会被处理。try块执行完成后,执行finally块的server.accept(null, this); ,这时第二个请求才被接收处理。
所以你要实现多连接的话,最好把finally块的server.accept(null, this); 的这句放在try块第一句就可以了。