返回

同步,异步,阻塞,非阻塞及 I/O 模型

后端

聊聊同步、异步、阻塞、非阻塞以及 I/O 模型

前言

在分布式系统和高并发编程中,理解同步、异步、阻塞和非阻塞 I/O 模型至关重要。这些概念决定了我们的代码如何与外部世界进行交互,并对系统性能和响应能力产生重大影响。

同步与异步

同步操作意味着调用方会在操作完成之前一直等待。异步操作则允许调用方继续执行,并在操作完成后通过回调或事件通知。

  • 同步:
String result = requestService.makeSyncRequest();
  • 异步:
requestService.makeAsyncRequest(result -> {
    // 操作完成后执行此代码
});

阻塞与非阻塞

阻塞操作意味着操作会阻止调用方线程,直到操作完成。非阻塞操作则不会阻止调用方线程,允许其继续执行。

  • 阻塞:
InputStream input = new FileInputStream("file.txt");
byte[] data = new byte[1024];
while ((input.read(data)) != -1) {
    // 处理数据
}
  • 非阻塞:
Selector selector = Selector.open();
selector.register(socket, SelectionKey.OP_READ);
while (true) {
    selector.select();
    Set<SelectionKey> keys = selector.selectedKeys();
    for (SelectionKey key : keys) {
        if (key.isReadable()) {
            // 处理数据
        }
    }
}

I/O 模型

I/O 模型了应用程序如何与操作系统进行交互以处理 I/O 请求。常见的 I/O 模型包括:

  • 阻塞 I/O: 应用程序会阻塞,直到 I/O 操作完成。
  • 非阻塞 I/O: 应用程序不会阻塞,而是轮询 I/O 状态。
  • 多路复用 I/O: 应用程序使用单线程来监控多个 I/O 事件。
  • 异步 I/O: 操作系统会通知应用程序 I/O 操作的完成。

Netty 示例

Netty 是一个高性能的 Java NIO 框架,它提供了对同步和异步 I/O 操作的支持。以下示例展示了如何使用 Netty 实现异步非阻塞服务器:

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new HttpResponseEncoder());
                pipeline.addLast(new StringDecoder());
                pipeline.addLast(new ChannelInboundHandlerAdapter() {
                    @Override
                    public void channelRead(ChannelHandlerContext ctx, Object msg) {
                        ByteBuf in = (ByteBuf) msg;
                        String request = in.toString(CharsetUtil.UTF_8);
                        String response = "Hello, " + request + "\n";
                        ctx.writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8));
                    }
                });
            }
        });
ServerSocketChannel serverSocketChannel = bootstrap.bind(8080).sync().channel();
serverSocketChannel.closeFuture().sync();

在 Netty 中,EventLoopGroup 管理事件循环,而 EventLoop 则处理 I/O 事件。异步非阻塞模式允许服务器处理多个请求,而不会阻塞线程。

结论

理解同步、异步、阻塞、非阻塞和 I/O 模型对设计高性能、高并发的应用程序至关重要。Netty 等框架提供了强大的 API,允许开发人员轻松实现这些概念,从而实现高效和可扩展的解决方案。