isConnectionPending()用于确认连接是否已发起但未完成,finishConnect()则负责完成连接并返回成功、继续中或失败结果;二者须按序配合使用,先查pending再finish,不可跳过前者直接调用后者。

在非阻塞模式下使用 SocketChannel 建立连接时,isConnectionPending() 和 finishConnect() 是一对协同工作的关键方法,用于判断连接是否正在异步进行、以及是否已完成或失败。
isConnectionPending() 的作用:确认连接是否“已发起但未完成”
调用 connect() 后,若通道处于非阻塞模式,该方法会立即返回 true(表示连接操作已启动但尚未完成),而不是阻塞等待。它不表示连接成功,仅说明底层 TCP 握手仍在进行中(比如 SYN 已发、SYN-ACK 未收全)。
常见误用:把它当作“连接是否成功”的判断依据——这是错误的。它只回答“有没有在连”,不回答“连没连上”。
finishConnect() 的职责:真正完成连接并报告结果
必须在 isConnectionPending() 返回 true 后,且通道就绪(如 SelectionKey.OP_CONNECT 就绪)时调用。它会尝试完成三次握手的最后一步,并返回:
立即学习“Java免费学习笔记(深入)”;
- true:连接成功建立(可开始读写)
- false:连接仍在进行中(罕见,通常说明底层还在等 ACK)
- 抛出 IOException:连接失败(如拒绝连接、超时、主机不可达)
典型配合流程(基于 Selector)
实际编码中,二者需按固定顺序配合使用:
- 设置通道为非阻塞:
channel.configureBlocking(false) - 发起连接:
channel.connect(new InetSocketAddress(host, port)) - 注册
OP_CONNECT到 Selector - 当 Selector 返回该 key 就绪时:
→ 先检查key.isConnectable()(等价于isConnectionPending()为 true)
→ 再调用channel.finishConnect()判断成败
→ 若成功,取消OP_CONNECT,注册OP_READ或OP_WRITE;若失败,关闭通道
为什么不能跳过 isConnectionPending() 直接调 finishConnect()?
虽然 JDK 允许这么做,但语义上不安全:
- 如果连接根本没发起(比如忘记调
connect()),finishConnect()会直接抛NoConnectionPendingException - 如果连接早已完成(比如 connect() 在阻塞模式下执行过),再次调用可能引发异常或行为未定义
- 先查
isConnectionPending()是一种防御性编程习惯,确保调用时机合理
不复杂但容易忽略。


















