通道(Channel)
通道(Channel)在Java NIO中是用于在缓冲区
和文件
、网络Socket
之间传输数据的重要组件。通道的使用可以提高数据传输的效率,可以在非阻塞IO操作
中使用,适合于处理大量数据的场景,例如文件复制、网络数据传输等
代码如下:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class ChannelExample {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
FileChannel inputChannel = fis.getChannel();
FileChannel outputChannel = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inputChannel.read(buffer) != -1) {
buffer.flip();
outputChannel.write(buffer);
buffer.clear();
}
inputChannel.close();
outputChannel.close();
fis.close();
fos.close();
}
}
上面代码中,首先创建了一个FileInputStream和一个FileOutputStream,然后通过它们分别获取了输入通道(inputChannel)
和输出通道(outputChannel)
。
使用ByteBuffer来缓冲数据,通过调用 inputChannel.read(buffer)
从输入通道读取数据到缓冲区,然后通过 outputChannel.write(buffer)
将数据从缓冲区写入输出通道。
选择器(Selector)
选择器(Selector)是Java NIO中的关键组件,用于实现多路复用非阻塞IO操作
,允许单个线程
管理多个通道
。通过选择器,可以有效地处理多个通道的IO事件
,提高系统的性能和资源利用率。
代码如下:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class SelectorExample {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8888));
serverSocketChannel.configureBlocking(false); //设置为非阻塞
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) { //接受连接并注册读事件
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(buffer);
if (bytesRead == -1) {
socketChannel.close();
} else {
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
}
}
keyIterator.remove();
}
}
}
}
在上面代码中,创建了一个Selector
对象,并注册了一个ServerSocketChannel
用于监听连接请求。通过调用 selector.select()
方法,我们等待IO事件发生。一旦有事件发生,我们通过遍历selectedKeys
来处理每个事件对应的SelectionKey。
OP_ACCEPT表示有新的连接请求,OP_READ表示有数据可读
通过选择器,可以使用单个线程有效地管理多个通道的IO操作
,提高系统的性能和响应速度。