BIO和NIO简单DEMO

本文通过DEMO展示了BIO和NIO两种不同的I/O模型。BIO每个连接需创建独立线程,CPU压力大,通常不推荐使用。而NIO在连接数量大时,虽然避免了线程创建,但遍历无消息的连接效率低下。为优化,可以引入多路复用器。
摘要由CSDN通过智能技术生成

BIO:线程模型

 BIO:server demo。缺陷:每一个连接创建一个线程,cpu压力太大。一般不用BIO。

public static void main(String[]args) throws IOException{
        ServerSocket serverSocket=new ServerSocket(9000);
        while (true){
            System.out.println("等待连接");
            final Socket socket=serverSocket.accept();
            System.out.println("有客户端连接");
            //handler(socket);
            new Thread(new Runnable() {
                public void run() {
                    try {
                        handler(socket);
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    private static void handler(Socket socket) throws IOException {
        byte[] bytes=new byte[1024];
        System.out.println("准备读取");
        int read=socket.getInputStream().read(bytes);
        System.out.println("读取完毕");
        if(read!=-1){
            System.out.println("接收到的数据:"+new String(bytes,0,read));
        }
        socket.getOutputStream().write("hello client!".getBytes());
        socket.getOutputStream().flush();
    }

NIO:

 NIO:server demo。

public class NioServer {
    private static List<SocketChannel> channelList;
    public static void main(String[] args) throws IOException {
        ServerSocketChannel channel=ServerSocketChannel.open();
        channel.socket().bind(new InetSocketAddress(9000));
        channel.configureBlocking(false);//非阻塞
        System.out.println("server启动成功");
        while (true){
            SocketChannel socketChannel=channel.accept();
            if(socketChannel!=null){
                System.out.println("有客户端连接");
                socketChannel.configureBlocking(false);//设置读取为非阻塞
                channelList.add(socketChannel);
            }
            Iterator<SocketChannel> i=channelList.iterator();
            while (i.hasNext()) {
                SocketChannel sc= i.next();
                ByteBuffer byteBuffer=ByteBuffer.allocate(128);
                int len=sc.read(byteBuffer);
                if(len>0){
                    System.out.println("接收到消息"+new String(byteBuffer.array()));
                }else if(len==-1){
                    i.remove();
                    System.out.println("客户端断开连接");
                }
            }
        }
    }
}

缺陷:当连接很多时,遍历channelList浪费时间,应该遍历有传递消息的连接。

优化:引入多路复用器:

public class NioSelectorServer {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel channel=ServerSocketChannel.open();
        channel.socket().bind(new InetSocketAddress(9000));
        channel.configureBlocking(false);//非阻塞
        Selector selector=Selector.open();
        channel.register(selector, SelectionKey.OP_ACCEPT);//selector注册连接事件
        System.out.println("server启动成功");
        while (true){
            selector.select();//阻塞等待事件发生
            Set<SelectionKey> selectionKeys=selector.selectedKeys();//获取全部事件
            Iterator<SelectionKey> iterator=selectionKeys.iterator();
            while (iterator.hasNext()){//遍历处理所有事件
                SelectionKey selectionKey=iterator.next();
                if(selectionKey.isAcceptable()){//有客户端连接
                    SocketChannel socketChannel=((ServerSocketChannel)selectionKey.channel()).accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector,SelectionKey.OP_READ);//注册数据读取事件
                }else if(selectionKey.isReadable()){//接收到消息
                    SocketChannel sc= (SocketChannel)selectionKey.channel();
                    ByteBuffer byteBuffer=ByteBuffer.allocate(128);
                    int len=sc.read(byteBuffer);
                    if(len>0){
                        System.out.println("接收到消息"+new String(byteBuffer.array()));
                    }else if(len==-1){
                        sc.close();
                        System.out.println("客户端断开连接");
                    }
                }
                iterator.remove();//去掉处理过的事件
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值