1.Bio与Nio的关系?
Nio是Bio的改进,但是Nio到底改进了什么?怎么实现的?有什么优势?等等问题都要从Bio找根源。
2.Bio是什么意思?
B I/O,意为Blocking I/O,即阻塞的I/O。
很明显重点在阻塞,但怎么就阻塞了?阻塞在哪了?阻塞带来了什么坏处?
3.Bio的工作模式
简单来说,在服务器中bio是一个连接由一个专门的线程来服务的工作模式。就像餐厅里来一个客人就给这个客人安排一个专用服务员,这个服务员就只服务这一个客人直到他离开为止。
如图所示每一个连接都享有一个线程的单独服务。
4.Bio工作模式的缺陷
(1)线程创建资源开销巨大。
如果有10000个连接怎么办?创建10000个线程?很明显不现实,太多的线程对系统资源的开销是巨大的。
(2)单个线程的资源浪费。
一个请求来了,如果这个线程从被创建为这个连接服务开始就一直在工工作,那么就不存在资源浪费,就像你找来一个服务员,他只服务一个客人,但他期间一直都有工作作,那么他的劳动力就算不上浪费。
但是绝大多数情况下客人多服务员的需求都是暂时的,服务员很多时候都在发呆玩手机,等待着回应客人的请求,这样这个服务员的劳动力就被浪费了。那么在Bio中线程等待服务的时候是什么样的呢,那就是阻塞,线程等待着为连接服务(读数据/写数据/业务处理),很多时候BIo的服务子线程都是在阻塞状态下的。
5.Bio阻塞在哪了?
bio的阻塞,主要体现在两个地方,如代码中注释所示。
①若一个服务器启动就绪,那么主线程就一直在等待着客户端的连接,这个等待过程中主线程就一直在阻塞。
②在连接建立之后,一个子线程服务于这个连接,那么这个子线程提供的服务无非就是socket通信,在读取到socket信息之前,这个子线程也是一直在等待,一直处于阻塞的状态下的。
注:代码中采用了连接池,这样可以节约一些线程重复创建的开销,但是这样的优化作用是有限的。
读者可以用windows 的telnet功能测试这个简单的服务器例子,以帮助加深对Bio的理解。
package com.zjl.bio;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @program: NettyTetst
* @description: Bio的简单例子
* @author: zoujunlin
* @create: 2020-05-31 23:17
**/
public class Bio implements Runnable{
private Socket socket;
public Bio(Socket socket){
this.socket= socket;
}
public static void main(String[] args) {
/*
采用线程池机制
1.创建一个线程池子
2.每有一个请求就用一个线程来与之通信
3.创建Socket服务
4.监听链接
5.打印客户端发送的字符
* */
ExecutorService executorsServics=Executors.newCachedThreadPool();//线程池
try {
ServerSocket serverSocket=new ServerSocket(1234);//注册serverSoket到1234端口
System.out.println("服务器准备就绪...");
while (true){
final Socket socket = serverSocket.accept();//1线程在这里被阻塞,只要没有连接,就一直阻塞
System.out.println("一个客户端连接到了服务器...");
executorsServics.execute(new Bio(socket));//创建线程执行任务
}
}catch (Exception e){
}
}
public void run() {
byte[] bytes = new byte[1024];
try{
InputStream inputStream = socket.getInputStream();
System.out.println("执行这个任务的线程是:"+Thread.currentThread().getName());
while (true){//循环读取
int read = inputStream.read(bytes);//2线程被阻塞的地方:只要读取不到数据就会一直阻塞
if(read!=-1){
System.out.println(new String(bytes,0,read));//byte按坐标转String
}else{
break;
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
System.out.println("线程"+Thread.currentThread().getName()+"维护的连接中断了!");
socket.close();//关闭socket连接
}catch (Exception e){
e.printStackTrace();
}
}
}
}
5 Nio
连接空值待补充。