Java高并发教程:详解NIO Channel(通道)类
Java高并发教程:详解NIO Channel(通道)类
NIO Channel
NIO中一个连接用一个Channel来表示。从更广泛的层面来说,一个通道可以表示一个底层的文件描述符,例如硬件设备、文件、网络连接等。然后,远远不止如此,除了可以对应到底层文件描述符,Java NIO的通道还可以更加细化。例如,对应不同的网络传输协议类型,再Java中都有不同的NIO Channel通道实现。
Channel的主要类型
以下这个四种通道,涵盖了文件IO、TCP网络、UDP IO基础IO:
FileChannel文件通道
FileChannel是专门操作文件的通道。通过FileChannel,既可以从一个文件中读取数据,也可以将数据写入到文件中。特别申明一下,FileChannel为阻塞模式,不能设置为非阻塞模式。
读取文件内容
@Test public void fileChannelReadFile() throws FileNotFoundException { try { RandomAccessFile reader = new RandomAccessFile("E:\\Hello.txt","r"); FileChannel channel = reader.getChannel(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int bufferSize = 1024; if(bufferSize > channel.size()){ bufferSize = (int) channel.size(); } ByteBuffer buffer = ByteBuffer.allocate(bufferSize); while (channel.read(buffer)>0){ outputStream.write(buffer.array(),0,buffer.position()); buffer.clear(); } String fileContent = new String(outputStream.toByteArray(), StandardCharsets.UTF_8); System.out.println(fileContent); }catch (IOException e) { e.printStackTrace(); } }
应该注意到,多个并发线程可以安全地使用FileChannels。然而,只有一次一个线程被允许,其涉及更新信道的位置或改变其文件大小的操作。这将阻止其他线程尝试类似的操作,直到前面的操作完成。 但是如果提供明确的频道位置的操作可以在不被阻塞并发运行。
写文件
@Test public void fileChannelWriteFile() { try { RandomAccessFile writer = new RandomAccessFile("E:\\NEW.txt","rw"); FileChannel channel = writer.getChannel(); ByteBuffer buffer = ByteBuffer.wrap("Hello World".getBytes(StandardCharsets.UTF_8)); channel.write(buffer); RandomAccessFile reader = new RandomAccessFile("E:\\\\NEW.txt","r"); System.out.println(reader.readLine()); reader.close(); }catch (IOException e) { e.printStackTrace(); } }
参考资料
- https://www.baeldung.com/java-filechannel
- 《Netty、Redis、Zookeeper高并发实战》