BIO
1. 什么是BIO
B I/O,意为Blocking I/O,即阻塞的I/O。
很明显重点在阻塞,但怎么就阻塞了?阻塞在哪了?阻塞带来了什么坏处?
2. BIO的代码实现:
- 服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(9090,20);
System.out.println("step1: new ServerSocket(9090) ");
while (true) { Socket client = server.accept(); System.out.println("step2:client\t" + client.getPort());
new Thread(() -> { InputStream in = null; try { in = client.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); while(true){ String dataline = reader.readLine();
if(null != dataline){ System.out.println(dataline); }else{ client.close(); break; } } System.out.println("客户端断开");
} catch (IOException e) { e.printStackTrace(); }
}).start();
} }
|
- 客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public static void main(String[] args) { try { Socket client = new Socket("192.168.150.11",9090);
client.setSendBufferSize(20); client.setTcpNoDelay(true); OutputStream out = client.getOutputStream();
InputStream in = System.in; BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while(true){ String line = reader.readLine(); if(line != null ){ byte[] bb = line.getBytes(); for (byte b : bb) { out.write(b); } } } } catch (IOException e) { e.printStackTrace(); } }
|
3. BIO的工作模式
graph TD
A[Client 1] --> S(Service 9090)
C[Client 2] --> S
D[Client 2] --> S
S --> F(Thread 1)
S --> E(Thread 2)
S --> G(Thread 3)
F --> H(Socket1 处理 Client 1 )
E --> I(Socket2 处理 Client 2 )
G --> V(Socket3 处理 Client 3 )
4. 为什么要使用多线程:
这是一个经典的每连接每线程的模型,之所以使用多线程,主要原因在于socket.accept()、socket.read()、socket.write()三个主要函数都是同步阻塞的,当一个连接在处理I/O的时候,系统是阻塞的,如果是单线程的话必然就挂死在那里;但CPU是被释放出来的,开启多线程,就可以让CPU去处理更多的事情。其实这也是所有使用多线程的本质:
5. BIO的缺点
(1)线程创建资源开销巨大。如果有10000个连接怎么办?创建10000个线程?很明显不现实,太多的线程对系统资源的开销是巨大的。
(2)单个线程的资源浪费。
一个请求来了,如果这个线程从被创建为这个连接服务开始就一直在工工作,那么就不存在资源浪费,就像你找来一个服务员,他只服务一个客人,但他期间一直都有工作作,那么他的劳动力就算不上浪费。
但是绝大多数情况下客人多服务员的需求都是暂时的,服务员很多时候都在发呆玩手机,等待着回应客人的请求,这样这个服务员的劳动力就被浪费了。那么在Bio中线程等待服务的时候是什么样的呢,那就是阻塞,线程等待着为连接服务(读数据/写数据/业务处理),很多时候BIo的服务子线程都是在阻塞状态下的。
基于以上不足出现了NIO