Java的BIO

Java的BIO教程

BIO 全称 Blocking IO,底层使用的是阻塞 IO 模型,它是面向流的。每次从流中读取一个或多个字节,直至读取所有字节,操作数据的时候,不能前后移动流中数据。

BIO介绍

网络编程的基本模型是客户端/服务端模型,是两个进程之间的通信。如果客户端和服务端建立了连接,双方就通过套接字(Socket)进行通信。

在 BIO 模型中,如果下图,服务端会有一个独立的 Acceptor 来统一接受客户端的连接,它接受到客户端的连接后会为每个客户端创建一个新的线程去进行客户端的请求处理,当线程处理完之后会立刻将结果返回给客户端,处理线程销毁。这个是一请求一应答模型,比较典型的同步阻塞 IO 模型。

01 BIO.png

从上面的 BIO 模型图中,我们可以看到,每当客户端一个请求过来的时候,都会新生成一个线程来处理请求信息。当客户端请求量比较少的时候还好,如果客户端访问量比较大的时候系统也会随之创建比较多的线程。Java 虚拟机的线程是非常宝贵的资源,如果线程创建过多,系统的性能就会下降。如果数量过多,会让系统发生宕机或者假死,不能够接受和处理新的请求。

就按照现实生活中举一个不恰当的例子,你去餐厅吃自助餐,每个客人去的时候,都会找一个服务员进行一对一服务,当客户走了,然后服务员也解雇了,等下次再有客人来的时候,会再现抓一个服务员进行一对一服务。(当然前提是服务员是随时都能找到的)如果不是吃饭的点,来店里吃饭的顾客比较少,这样还是能够应付的,如果吃饭的人比较多,服务员的数量和客人的数量是 1:1 的,到时候店里估计连落脚的地方都没有了,服务员为客人服务的时候估计都挪不了步子,人挤人,那所有的人就只能堵在那边,什么事情都做不了,最后客人都饿死了。

伪异步I/O

针对同步 I/O,一个请求就创建一个线程,这样对资源的消耗太大了,容易使系统假死,不能再对外提供服务。这个时候就有人想到了使用线程池来对请求进行处理。项目每次启动的时候,我们先将线程池创建好,请求的时候直接从线程池中拿线程,如果线程池中线程被占用完了,那么就将新请求放入队列当中,这样即使你客户端有再多的请求,也不会让系统因为创建线程太多而假死了。

02 伪异步IO.png

同步阻塞的概念我们在之前的文章中了解过,它是针对于服务端而言的,从上图中你可以发现,它的处理结果还是客户端请求后一直在那边等,所以还是同步阻塞的模型。它只是很好的解决了服务端创建线程的压力,可以让服务端不会由于线程创建过多而导致假死。

接着上面不恰当的客人去餐厅吃饭的例子,没有服务员服务客人就不能用餐。我们招一批服务员,如果服务员对人对服务不够了,我们可以让客人坐在一个区域等待,等前面的客人走了,再让服务员服务下一位等待的客人,这样的话,就能够保证餐厅能够持续的运行,当然客人等待的时间有长有短。

BIO总结

BIO 是同步阻塞 IO 模型。它是最简单的网络通信编程,一请求一等待。每次请求服务端都会创建一个线程进行处理。线程处理完之后就会销毁,这样会导致资源浪费,所以就有了伪异步的概念,使用线程池来进行处理客户端请求。