当前位置:首页 > Java

java如何使用nio

2026-03-21 13:59:15Java

Java NIO 基础概念

Java NIO(New I/O)是一种基于通道(Channel)和缓冲区(Buffer)的高效I/O模型,支持非阻塞操作和选择器(Selector)机制,适用于高并发场景。

核心组件

缓冲区(Buffer)
缓冲区是数据的临时存储区,分为多种类型(如 ByteBufferCharBuffer)。通过 allocate() 方法创建:

java如何使用nio

ByteBuffer buffer = ByteBuffer.allocate(1024); // 分配1024字节的缓冲区

通道(Channel)
通道是数据双向传输的管道,常见实现类包括 FileChannelSocketChannelServerSocketChannel

文件读写示例

通过 FileChannel 读写文件:

java如何使用nio

try (FileChannel channel = FileChannel.open(Paths.get("test.txt"), StandardOpenOption.READ)) {
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    channel.read(buffer); // 读取数据到缓冲区
    buffer.flip(); // 切换为读模式
    while (buffer.hasRemaining()) {
        System.out.print((char) buffer.get());
    }
} catch (IOException e) {
    e.printStackTrace();
}

非阻塞网络通信

使用 Selector 实现非阻塞Socket通信:

Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 注册接受连接事件

while (true) {
    selector.select(); // 阻塞直到有事件就绪
    Set<SelectionKey> keys = selector.selectedKeys();
    Iterator<SelectionKey> iter = keys.iterator();
    while (iter.hasNext()) {
        SelectionKey key = iter.next();
        if (key.isAcceptable()) {
            SocketChannel client = serverChannel.accept();
            client.configureBlocking(false);
            client.register(selector, SelectionKey.OP_READ); // 注册读事件
        } else if (key.isReadable()) {
            SocketChannel client = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(128);
            client.read(buffer);
            buffer.flip();
            System.out.println("Received: " + new String(buffer.array()));
        }
        iter.remove();
    }
}

内存映射文件

通过 FileChannel.map() 实现高效大文件处理:

try (FileChannel channel = FileChannel.open(Paths.get("large.bin"), 
        StandardOpenOption.READ, StandardOpenOption.WRITE)) {
    MappedByteBuffer mappedBuffer = channel.map(
        FileChannel.MapMode.READ_WRITE, 0, channel.size());
    mappedBuffer.putInt(0, 123); // 直接修改文件内容
} catch (IOException e) {
    e.printStackTrace();
}

注意事项

  • 缓冲区状态管理:调用 flip()clear()rewind() 切换读写模式。
  • 资源释放:确保通道和选择器通过 try-with-resources 或手动关闭。
  • 性能优化:使用直接缓冲区(ByteBuffer.allocateDirect())减少JVM堆内存拷贝开销。

分享给朋友:

相关文章

java如何创建包

java如何创建包

创建Java包的步骤 在Java中,包(package)用于组织和管理类文件,避免命名冲突。以下是创建Java包的详细方法: 定义包名 在Java源文件的开头使用package关键字声明包名。包名…

java如何实现异步

java如何实现异步

Java实现异步的方法 Java中实现异步编程可以通过多种方式,每种方式适用于不同的场景和需求。以下是常见的实现方法: 使用Thread类 创建新线程执行异步任务是最基础的方式。通过继承Thread…

react如何使用swiper

react如何使用swiper

安装 Swiper 依赖 在 React 项目中使用 Swiper 前,需要安装 Swiper 的核心库和 React 组件库。通过 npm 或 yarn 安装以下依赖: npm install s…

react refs 如何使用

react refs 如何使用

React Refs 的基本概念 Refs 是 React 提供的一种访问 DOM 节点或 React 组件实例的方式。通常在 React 的数据流中,父子组件通过 props 进行通信,但在某些情况…

如何学习java语言

如何学习java语言

学习Java语言的系统方法 理解基础概念 Java是一种面向对象的编程语言,掌握基础概念如变量、数据类型、运算符、控制流语句(if-else、循环)是第一步。熟悉类和对象的概念,理解封装、继承和多态三…

java如何调用另一个类的方法

java如何调用另一个类的方法

调用另一个类的方法 在Java中调用另一个类的方法,通常需要创建该类的对象或直接通过类名调用(静态方法)。以下是几种常见的方式: 通过对象实例调用实例方法 创建一个目标类的对象,通过对象调用其方法。…