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高並發實戰》