java-NIO

NIO的定义   

       Java NIO(New Input/Output)是Java编程语言中的一个提供了高性能、高度可扩展的I/O操作的API。它是在Java 1.4版本中引入的,用于改进传统的Java I/O操作。

     Java NIO提供了一套基于通道(Channel)和缓冲区(Buffer)的I/O机制,与传统的流(Stream)I/O相比,具有更高的效率和更低的资源消耗。它允许使用非阻塞(非阻塞)I/O,可以在单个线程中同时处理多个连接,提高了系统的并发性能。

     Java NIO中的关键组件包括通道(Channel)、选择器(Selector)和缓冲区(Buffer)。通道是与I/O设备进行交互的通道,可以向通道写入或读取数据。选择器是用于高效地监控多个通道的对象,可以同时监控多个通道的状态。缓冲区是用来存储数据的对象,可以读取或写入数据。

  实现以下功能:

  • 非阻塞式I/O操作
  • 网络通信
  • 文件操作
  • 多线程并发处理
  • 零拷贝技术
  • 内存映射文件等

应用场景 

  1. 网络通信 (Non-blocking I/O): 示例代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NonBlockingClient {
    public static void main(String[] args) throws IOException {
        SocketChannel channel = SocketChannel.open();
        channel.configureBlocking(false);
        
        if (channel.connect(new InetSocketAddress("localhost", 8080))) {
            // Handle connection immediately
            sendData(channel);
        } else {
            // Connection is in progress
            while (!channel.finishConnect()) {
                // Wait until the connection is established
            }
            sendData(channel);
        }
        
        channel.close();
    }
    
    private static void sendData(SocketChannel channel) throws IOException {
        String message = "Hello, Server!";
        ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
        channel.write(buffer);
    }
}

解释与说明: 这个示例代码展示了如何使用非阻塞式的SocketChannel进行网络通信。首先创建一个SocketChannel对象,并设置为非阻塞模式(channel.configureBlocking(false))。然后使用channel.connect()方法尝试连接远程服务器。如果连接是立即可用的,则立即发送数据(sendData方法)。否则,我们需要在while循环中等待连接完成(channel.finishConnect()),然后再发送数据。

  1. 文件操作 (File I/O): 示例代码:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class FileIOExample {
    public static void main(String[] args) throws IOException {
        // Open file channel in non-blocking mode
        Path filePath = Paths.get("file.txt");
        FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ);
        channel.configureBlocking(false);
        
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (channel.read(buffer) != -1) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                System.out.print((char) buffer.get());
            }
            buffer.clear();
        }
        
        channel.close();
    }
}

解释与说明: 该示例代码演示了如何使用非阻塞式的FileChannel从文件中读取数据。首先打开文件通道(channel = FileChannel.open(filePath, StandardOpenOption.READ)),并将其配置为非阻塞模式(channel.configureBlocking(false))。然后创建一个ByteBuffer对象,用于读取文件中的数据。使用channel.read(buffer)方法从文件中读取数据,并在控制台上打印出来。

  1. 多线程并发处理 (Multithreading): 示例代码:

import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NonBlockingServerHandler implements Runnable {
    private final SocketChannel channel;
    private final ByteBuffer buffer;
    
    public NonBlockingServerHandler(SocketChannel channel) {
        this.channel = channel;
        this.buffer = ByteBuffer.allocate(1024);
    }
    
    @Override
    public void run() {
        try {
            while (channel.read(buffer) != -1) {
                buffer.flip();
                while (buffer.hasRemaining()) {
                    System.out.print((char) buffer.get());
                }
                buffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

解释与说明: 该示例代码展示了一个多线程处理非阻塞式SocketChannel的示例。在一个线程中,使用channel.read(buffer)方法从SocketChannel中读取数据,并处理读取到的数据。当读取到-1时,表示连接已关闭,处理结束。在finally块中关闭SocketChannel。

  1. 零拷贝技术 (Zero Copy): 示例代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;

public class ZeroCopyExample {
    public static void main(String[] args) throws IOException {
        FileChannel fileChannel = new FileInputStream("file.txt").getChannel();
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("localhost", 8080));
        
        while (!socketChannel.finishConnect()) {
            // Wait until the connection is established
        }
        
        long transferred = fileChannel.transferTo(0, fileChannel.size(), socketChannel);
        System.out.println("Transferred bytes: " + transferred);
        
        fileChannel.close();
        socketChannel.close();
    }
}

解释与说明: 该示例代码展示了使用零拷贝技术将文件内容从文件通道传输到SocketChannel。首先打开文件通道(fileChannel = new FileInputStream("file.txt").getChannel()),然后打开SocketChannel(socketChannel = SocketChannel.open())并连接到远程服务器。使用fileChannel.transferTo()方法将文件内容直接传输到SocketChannel,避免了数据复制。最后关闭文件通道和SocketChannel。

  1. 内存映射文件 (Memory-mapped Files): 示例代码:

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MemoryMappedFileExample {
    public static void main(String[] args) throws IOException {
        RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
        FileChannel channel = file.getChannel();
        
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
        
        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get());
        }
        
        buffer.put(10, (byte) '!');
        buffer.force();
        
        channel.close();
    }
}

解释与说明: 该示例代码演示了如何使用内存映射文件(MappedByteBuffer)来读取和写入文件内容。首先打开RandomAccessFile对象(file = new RandomAccessFile("file.txt", "rw")),然后获取文件通道(channel = file.getChannel())。使用channel.map()方法创建一个MappedByteBuffer对象,指定文件映射模式和起始位置。可以直接通过MappedByteBuffer对象读取和写入文件内容。在操作完成后,调用buffer.force()方法确保数据被刷新到磁盘上,然后关闭文件通道。

总结 

     Java NIO相较于旧的IO(BIO)有以下几个主要的优势:

  1. 非阻塞IO操作:Java NIO提供了非阻塞IO操作,使得一个线程能够处理多个请求。在旧的IO中,一个线程一次只能处理一个请求,而在NIO中,一个线程可同时管理多个请求,提高了系统的吞吐量。

  2. 选择器(Selector):选择器是Java NIO中非常重要的一个概念。它允许一个线程同时监听多个通道的事件。通过选择器,我们可以用一个线程处理多个通道的IO操作,减少了线程的开销。

  3. 缓冲区(Buffer):NIO中使用缓冲区进行数据读写。缓冲区可以直接与通道进行交互,提高了IO的效率。同时,缓冲区还提供了不同类型的视图,例如ByteBuffer、CharBuffer等,方便不同类型的数据操作。

  4. 通道(Channel):通道是Java NIO中处理输入输出的一种方式。通道可以分为可读、可写、可读可写的不同类型。通过通道,我们可以实现与文件、网络等资源的交互。

  5. 非堵塞式的文件IO:NIO中提供了非堵塞式的文件IO操作,可以异步读写文件,不需要等待IO操作完成。

  6. 内存映射文件(Memory-Mapped File):NIO中引入了内存映射文件的概念,允许文件直接映射到内存,从而实现文件的快速读写。

     

你可能感兴趣的:(java,nio,开发语言)