面试题答案
一键面试同步IO模型与异步IO模型在代码实现层面的主要不同点
- 调用方式:
- 同步IO:调用者发起IO操作后,会阻塞等待IO操作完成,直到操作结束才会继续执行后续代码。
- 异步IO:调用者发起IO操作后,不会阻塞等待,而是继续执行后续代码,IO操作完成后通过回调或其他机制通知调用者。
- 线程模型:
- 同步IO:通常在单个线程内完成IO操作,线程在等待IO的过程中无法执行其他任务。
- 异步IO:可以使用多线程或线程池来处理IO操作,主线程不会被IO操作阻塞,提高了系统的并发处理能力。
- 代码结构:
- 同步IO:代码结构相对简单,按照顺序执行,容易理解和调试。
- 异步IO:代码结构相对复杂,需要处理回调函数或使用Future等异步处理机制,可能涉及到多线程编程。
同步IO代码示例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SynchronousIOExample {
public static void main(String[] args) {
try {
// 创建一个BufferedReader用于读取控制台输入
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入内容:");
// 这里readLine()方法是同步的,会阻塞线程直到用户输入并回车
String input = reader.readLine();
System.out.println("你输入的内容是:" + input);
} catch (IOException e) {
e.printStackTrace();
}
}
}
异步IO代码示例(使用Java NIO和Future)
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class AsynchronousIOExample {
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
Future<Void> future = client.connect(java.net.InetSocketAddress.createUnresolved("example.com", 80));
// 这里connect是异步的,不会阻塞主线程,我们可以做其他事情
future.get(); // 这里使用Future.get()等待连接完成,如果不需要等待可以省略
ByteBuffer buffer = ByteBuffer.wrap("GET / HTTP/1.1\r\n\r\n".getBytes());
Future<Integer> writeFuture = client.write(buffer);
int bytesWritten = writeFuture.get();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
Future<Integer> readFuture = client.read(readBuffer);
int bytesRead = readFuture.get();
readBuffer.flip();
byte[] response = new byte[bytesRead];
readBuffer.get(response);
System.out.println(new String(response));
client.close();
}
}
另外一种基于回调的异步IO示例:
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.net.InetSocketAddress;
import java.io.IOException;
public class AsynchronousIOExampleWithCallback {
public static void main(String[] args) {
try {
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
client.connect(new InetSocketAddress("example.com", 80), null, new CompletionHandler<Void, Void>() {
@Override
public void completed(Void result, Void attachment) {
try {
ByteBuffer buffer = ByteBuffer.wrap("GET / HTTP/1.1\r\n\r\n".getBytes());
client.write(buffer, null, new CompletionHandler<Integer, Void>() {
@Override
public void completed(Integer result, Void attachment) {
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
client.read(readBuffer, null, new CompletionHandler<Integer, Void>() {
@Override
public void completed(Integer result, Void attachment) {
readBuffer.flip();
byte[] response = new byte[result];
readBuffer.get(response);
System.out.println(new String(response));
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
}
});
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
}
});
// 主线程可以继续执行其他任务,而不是阻塞等待IO操作完成
Thread.sleep(10000);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}