多线程BIO服务器虽然解决了单线程BIO无法处理并发的弱点,但是也带来一个问题:如果有大量的请求连接到我们的服务器上,但是却不发送消息,那么我们的服务器也会为这些不发送消息的请求创建一个单独的线程,那么如果连接数少还好,连接数一多就会对服务端造成极大的压力。所以如果这种不活跃的线程比较多,我们应该采取单线程的一个解决方案,但是单线程又无法处理并发,这就陷入了一种很矛盾的状态,于是就有了NIO。
05 NIO
5.1 NIO的引入
我们先来看看单线程模式下BIO服务器的代码,其实NIO需要解决的最根本的问题就是存在于BIO中的两个阻塞,分别是等待连接时的阻塞和等待数据时的阻塞。
- public class Server {
- public static void main(String[] args) {
- byte[] buffer = new byte[1024];
- try {
- ServerSocket serverSocket = new ServerSocket(8080);
- System.out.println("服务器已启动并监听8080端口");
- while (true) {
- System.out.println();
- System.out.println("服务器正在等待连接...");
- //阻塞1:等待连接时阻塞
- Socket socket = serverSocket.accept();
- System.out.println("服务器已接收到连接请求...");
- System.out.println();
- System.out.println("服务器正在等待数据...");
- //阻塞2:等待数据时阻塞
- socket.getInputStream().read(buffer);
- System.out.println("服务器已经接收到数据");
- System.out.println();
- String content = new String(buffer);
- System.out.println("接收到的数据:" + content);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
我们需要再老调重谈的一点是,如果单线程服务器在等待数据时阻塞,那么第二个连接请求到来时,服务器是无法响应的。如果是多线程服务器,那么又会有为大量空闲请求产生新线程从而造成线程占用系统资源,线程浪费的情况。
那么我们的问题就转移到,如何让单线程服务器在等待客户端数据到来时,依旧可以接收新的客户端连接请求。
5.2 模拟NIO解决方案
如果要解决上文中提到的单线程服务器接收数据时阻塞,而无法接收新请求的问题,那么其实可以让服务器在等待数据时不进入阻塞状态,问题不就迎刃而解了吗?
(编辑:ASP站长网)
|