文章目录
背景:至于为什么有这篇博客的产生呢?因为最近在学习 Tomcat,而 Tomcat 中又涉及到了 BIO、NIO、AIO、APR,这四种 IO。所以,我就简要地学习了下 BIO、NIO。现在大致知道了它们是什么意思,怎么用。等以后接触到 Netty 的时候可以真正地去了解下它们呢~~
1. BIO & NIO
1.1 阻塞&非阻塞、同步&异步
阻塞与非阻塞指的是调用者在等待返回结果时的状态
- 阻塞:在调用返回结果前,当前线程会被挂起,并在得到结果后返回
- 非阻塞:如果不能立刻得到结果,该调用不会阻塞当前线程(调用者需要定时轮询查询处理状态)
同步与异步指的是具体的通信机制
- 同步:调用者等待返回结果
- 异步:调用者不需要等待返回结果,被调用者会通过回调等形式通知调用者
举个例子:应用程序和操作系统处理 IO 事件所采用的的方式
同步:应用程序直接参与 IO 读写的操作
异步:所有的 IO 操作都交给操作系统处理,应用程序只需要等待通知
IO 涵盖文件、网络、内存以及标准输入输出。这里主要涉及文件 IO、网络 IO
1.2 BIO
1.2.1 BIO 简介
BIO 是基于流进行读写的,而是是阻塞的,整体性能比较差。
基于流:基于流意味着每次从流中读取一个字节或多个字节,直至读完所有字节,它们没有被缓存在任何地方。此外,也不能前后移动流中的数据。如果需要移动的话,就需要将数据缓存到一个缓冲区中
阻塞的:当一个线程调用 read() 或 write() 方法时,该线程就会被阻塞,直至数据读取完毕或数据完全写入。但是,该线程在此期间不能干任何事
1.2.2 BIO 案例
场景一:文件 IO。使用文件字节输入流(BIO)读取某个文件
BIO 从一个阻塞流中一个/多个字节一个字节的读取数据
public class BioTest {
public static void main(String[] args) throws Exception{
String filePath = System.getProperty("user.dir") + File.separator + "hello.txt";
FileInputStream fis = new FileInputStream(filePath);
int data = 0;
while ((data = fis.read()) != -1) {
System.out.print((char)data);
}
}
}
场景二:网络 IO。使用 BIO 进行网络通信。
网络通信中,需要通过 Socket 在客户端与服务端建立双向链接以实现通信。主要步骤如下:
- 服务端监听某个端口是否有链接请求
- 客户端向服务端发出链接请求
- 服务端向客户端返回 Accept 消息,此时链接成功
- 客户端和服务器通过 Send()、Write() 等方法与对方通信
- 关闭连接
// 服务端
public class Server {
public static void main(String[] args) throws Exception{
// 监听 8080 端口
ServerSocket server = new ServerSocket(8080);
// 等待请求
Socket socket = server.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("客户端请求:" + br.readLine());
// 响应客户端
BufferedReader serverInput = new BufferedReader(new InputStreamReader(System.in));
String response = serverInput.readLine();
PrintWriter pw = new PrintWriter(socket.getOutputStream());
while (!"exit".equals(response)) {
pw.println(response);
pw.flush();
System.out.println("客户端请求:" + br.readLine());
response = serverInput.readLine();
}
br.close();
pw.close();
socket.close();
server.close();
}
}
// 客户端
public class Client {
public static