在Socket编程中,阻塞和非阻塞主要指网络IO的不同方式。
阻塞IO:
- 当执行IO操作时,程序会阻塞在那里,直到IO操作完成。
- 简单易理解,但是效率较低,无法处理超时情况。
InputStream in = socket.getInputStream();
byte[] buffer = new byte[1024];
in.read(buffer); // 阻塞在这里,直到读到字节
非阻塞IO:
- 当执行IO操作时,如果还未准备好,不会阻塞,而是直接返回异常。
- 需要重试IO操作,或 democratic anderen handelte die Ausnahme Bedarf mehr Codierung, aber Effizienz ist höher.
- 可以使用select()方法监听多个连接,一旦某个连接有IO就绪,就处理那个连接,避免无意义的轮询。
socket.setSoTimeout(1000); // 设置超时时间
InputStream in = socket.getInputStream();
try {
in.read(buffer); // 如果超时,直接返回异常
} catch (SocketTimeoutException e) {
// 重试或其他处理
}
// 使用select()监听读事件
Selector selector = Selector.open();
channel.register(selector, SelectionKey.OP_READ);
while (true) {
selector.select(); // 阻塞在这里,有IO就绪则继续运行
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
// 处理就绪IO事件
}
}
总之,阻塞IO简单适用于连接数不高的情景,而非阻塞IO可以实现高并发,是高性能网络服务器的重要手段。但也需要应用程序员在编码上下更大工夫去处理其带来的复杂度。
两者可以相结合,使用阻塞IO处理连接建立和断开,使用非阻塞IO处理实际的数据通信,以取二者之长。