谈谈传统BIO网络编程模型的局限性与NIO

先来看看我们的server端:

创建一个serversocket,进行监听,每来一个客户端,就启动一个新启动为其服务:

private void createListenSocket() {
        //如果创建监听socket的时候发生异常,将会隔WAIT_TIME毫秒重试,直到成功
        while (true){
            try {
                serverSocket = new ServerSocket(LISTEN_PORT);
                Log.info("创建监听socket成功,正在监听...");
                break;
            } catch (IOException e) {
                Log.error("创建监听socket失败,原因:"+e.getMessage()+WAIT_TIME+"ms后重建");
                ThreadUtils.sleep(WAIT_TIME);
            }
        }
    }
private void listen() throws IOException {
        Socket socket = null;
        //启动一个死循环来监听连接本服务器的socket
        while ((socket = server.accept()) != null) {
            // 来访客户记录到服务器:
            Destination destination = new Destination();
            destination.setSocket(socket);
            server.newDestination(destination);
            //启动一条子线程来处理连接本服务器的socket消息收发
            new SubListenThread(destination,server).start();

        }
    }

以上代码来自我半年前编写的一个远控程序服务端。在这个模型当中,服务端线程与客户端线程是1:1的关系,也就是说有多少个客户端,服务端就得创建多少个线程。

在java当中,创建线程的代价是很大的。如果有几千个客户端,这个程序是撑不住的。

那么像旺旺这种在线量可以达到几百万的应用,在单个机器上,势必要用一种比BIO更好的编程模型来实现。

那么NIO就可以解决这种应用场景。

关于NIO的教程,网上有非常多的详细教程,在这里就不赘述。就简单说说NIO编程模型:

首先,我们有几个基本概念:

1.channel 大家可以把它想象成stream,只不过我们可以通过channel进行双工通信,也就是能读又能写。

2.buffer 可以看做是一段缓存,我们能通过这么一段缓存对channel进行读写。

3.selector 中文直接翻译过来就是选择器,因为在NIO当中,我们不通过传统的一个线程处理一个客户端,而是通过轮询的方式知道哪些客户端可读、可连接,从而实现1:n的模型。

那么NIO的编程模型如下:

通过一个selector,客户端会连接到这个selector,我们可以通过一个死循环不断地轮询selector有哪些客户端,然后一旦监听到可读或者可连接事件,我们就进行相应的业务逻辑处理,该读读,该写写。

以下为一个简单多人聊天室部分源码:

看起来还是很复杂的,至少比传统的BIO通信模型复杂。

使用原生的nio api进行编程很难,而且这玩意还有bug,据说在1.8以上版本仍存在空轮询BUG,会让CPU飙到100%。

所以说,如果可以的话,尽量使用一些第三方框架,比如netty。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值