BIO

1. 什么是BIO

B I/O,意为Blocking I/O,即阻塞的I/O。

很明显重点在阻塞,但怎么就阻塞了?阻塞在哪了?阻塞带来了什么坏处?

2. BIO的代码实现:

  1. 服务端
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(); //阻塞1
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(); //阻塞2

if(null != dataline){
System.out.println(dataline);
}else{
client.close();
break;
}
}
System.out.println("客户端断开");

} catch (IOException e) {
e.printStackTrace();
}


}).start();

}
}
  1. 客户端
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