面试题答案
一键面试基本步骤
- 创建AsynchronousSocketChannel或AsynchronousServerSocketChannel:在文件读取场景中,我们使用
AsynchronousSocketChannel
来处理文件相关的异步I/O操作(虽然是文件,但AIO的设计理念类似网络I/O处理方式)。 - 初始化缓冲区:使用
ByteBuffer
来存储从文件中读取的数据。 - 注册回调处理程序:通过
Future
或CompletionHandler
来处理I/O操作的结果。对于大数据文件读取,通常使用CompletionHandler
来避免阻塞主线程。 - 读取数据:利用
AsynchronousSocketChannel
的read
方法发起异步读取操作。 - 处理数据:当读取操作完成后,在回调方法中处理读取到的数据,例如将每行记录存储到合适的数据结构中。
关键代码片段
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.net.InetSocketAddress;
public class AIODemo {
private static final int BUFFER_SIZE = 1024;
private final AsynchronousSocketChannel channel;
private final ByteBuffer byteBuffer;
private final CharBuffer charBuffer;
private final List<String> records = new ArrayList<>();
private StringBuilder currentLine = new StringBuilder();
public AIODemo() throws Exception {
channel = AsynchronousSocketChannel.open();
// 这里假设连接到一个模拟提供大数据文件内容的服务端
channel.connect(new InetSocketAddress("localhost", 8080)).get();
byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
charBuffer = CharBuffer.allocate(BUFFER_SIZE);
}
public void readData() {
channel.read(byteBuffer, null, new CompletionHandler<Integer, Void>() {
@Override
public void completed(Integer result, Void attachment) {
if (result == -1) {
// 数据读取完毕
if (currentLine.length() > 0) {
records.add(currentLine.toString());
}
try {
channel.close();
processRecords();
} catch (Exception e) {
e.printStackTrace();
}
return;
}
byteBuffer.flip();
StandardCharsets.UTF_8.decode(byteBuffer, charBuffer, false);
charBuffer.flip();
while (charBuffer.hasRemaining()) {
char c = charBuffer.get();
if (c == '\n') {
records.add(currentLine.toString());
currentLine.setLength(0);
} else {
currentLine.append(c);
}
}
charBuffer.clear();
byteBuffer.clear();
channel.read(byteBuffer, null, this);
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void processRecords() {
for (String record : records) {
System.out.println(record);
// 这里可以进行记录的后续处理
}
}
public static void main(String[] args) {
try {
AIODemo demo = new AIODemo();
demo.readData();
// 主线程可以继续执行其他任务,这里简单让主线程等待一会以确保数据读取和处理完成
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
上述代码实现了通过AIO从类似网络流(假设文件内容通过网络服务模拟提供)中读取数据,按行存储到List
中,并在读取完成后进行简单处理。实际应用中,可能需要根据具体场景调整连接逻辑(例如改为从文件路径读取文件内容而不是网络连接)。