AsynchronousServerSocketChannel提供两种accept方式:Future方式需调用get()阻塞等待,非真异步;CompletionHandler方式通过回调实现纯异步,推荐使用。

接收连接的两种启动方式
AsynchronousServerSocketChannel 提供两个 accept 方法入口,本质是同步发起、异步执行:
-
Future
accept() :立即返回 Future 对象,不阻塞调用线程;后续需显式调用get()才能获取连接通道——此时线程会挂起等待,失去“真异步”意义。 -
void accept(A attachment, CompletionHandler
handler) :注册回调处理器,连接就绪或失败时由底层 I/O 线程自动触发completed()或failed(),全程无主动等待,是推荐的纯异步路径。
CompletionHandler 中的典型处理逻辑
一旦连接建立成功,completed(AsynchronousSocketChannel ch, Void att) 被调用。这里需做三件事:
- 立即再次调用
accept(null, this),保持监听循环不断,否则服务器只处理一次连接就停止收新请求。 - 对刚拿到的
ch(即客户端通信通道)配置读写超时、缓冲区等选项,例如:ch.setOption(StandardSocketOption.SO_RCVBUF, 65536)。 - 启动该连接的数据交互,比如调用
ch.read(buffer, null, readHandler)进入异步读流程,避免阻塞当前回调线程。
线程与资源调度的关键约束
异步通道本身是线程安全的,但 accept 操作有排他性限制:
- 同一时刻只允许一个 accept 操作处于进行中;若在前一个未完成时又调用 accept,会抛出
AcceptPendingException。 - CompletionHandler 的所有方法(
completed/failed)默认由AsynchronousChannelGroup绑定的线程池执行;若未显式指定 group,则使用 JVM 默认的全局线程池,可能引发资源争抢。 - 建议显式创建带固定大小线程池的 group:
AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(16)),便于监控和限流。
连接就绪到数据可读之间的衔接
accept 成功仅表示 TCP 三次握手完成,不代表客户端已发数据。因此不能直接 read:
- 必须在
completed()中为新 channel 注册读操作,如:ch.read(buffer, buffer, readHandler)。 - readHandler 的
completed()收到字节数 > 0,才代表有有效数据到达;若为 0,可能是远端关闭连接(需检查ch.isOpen()和ch.isConnectionOpen())。 - 注意 ByteBuffer 状态管理:每次 read 前需调用
buffer.clear(),读完后用buffer.flip()准备读取内容,避免数据错位或丢包。


















