栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

BIO NIO AIO 的区别

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

BIO NIO AIO 的区别

首先要了解 阻塞非阻塞 同步异步 同步异步:

同步:是指发发送的一个消息 一个请求 需要对面返回 一个消息或者一个状态! 如果没有返回需要一直等待返回

异步:异步调用请求发送后,调用者无需等待消息返回便可进行其他操作,消息会以通知的方式告知调用者 就比如 你发送个微信 不需要立马回复 等一段时间 或者 等对方心情好在回复(添狗)

阻塞非阻塞:

阻塞:当前消息请求发送 没有结构返回 那么 当前线程会被挂起 直至返回消息

非阻塞:不能立刻得到结果之前,该调用不会阻塞当前线程!想干别的还可以干

BIO:

BIO(Blocking I/O) 同步阻塞IO

JDK1.4之前唯一选择, 只有这一种IO模型

问题:

有多个客户端进行连接时, 如: client1, client2 进行连接, 由于client1先与服务端进行了连接, 此时服务端只能处理client1的请求, 什么时候client1处理完, 什么时候才能处理其他的请求, 服务端的线程一直处理client1的请求, 所以再有其他的请求, 是没有办法处理的TCP/IP底层使用的是BIO, 同步阻塞的IO, 发起请求后, 必须等待接收到响应之后, 代码才能继续向下执行, 并且服务端一个线程只能处理一个客户端的一个请求!

解决办法 ;

package com.mcc.bio;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class MyServer {
    public static void main(String[] args) {
        try {
            //1.创建ServerSocket, 自动监听指定的ip+port
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("等待客户端连接");
            for(;;){
                //2.阻塞等待客户端的连接
                Socket accept = serverSocket.accept();
                System.out.println("客户端连接了");
                System.out.println("等待接受客户端的消息");
                
                new Thread(() -> {
                    for(;;){
                        //3.同步阻塞接受客户端的消息
                        try {
                            InputStream inputStream = accept.getInputStream();
                            DataInputStream dataInputStream = new DataInputStream(inputStream);
                            System.out.println("接收到客户端消息: "+dataInputStream.readUTF());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.mcc.bio;

import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;


public class MyClient1 {
    public static void main(String[] args) {
        try {
            //1.创建客户端Socket, 自动连接指定的ip+port
            Socket socket = new Socket("127.0.0.1", 9999);
            Scanner scanner = new Scanner(System.in);
            System.out.println("向服务端发送消息");
            for(;;){
                //向服务端输出
                DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                String next = scanner.next();
                dataOutputStream.writeUTF("客户端1"+next);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

每个客户端需要对应服务端的一个子线程。 所以有多少个客户端, 服务端就需要创建多少个子线程。如果客户端特别多,几万甚至几百万,服务器端就需要有几万甚至几百万的子线程。 由于每个子线程都有自己的独立线程区,这么多子线程可能就产生内存不足等问题。而且这么多的子线程也需要进行调度, 切换, 销毁这也是非常消耗性能的

虽然可以解决一个服务端处理多个客户端,但是因为过多的子线程导致系统资源消耗过多,线程切换导致性能下降也是我们不得不需要考虑的问题

可以使用线程池,在一定程度上提升程序性能

NIO:

NIO称为New IO(新的IO)又称Non-Blocking IO(非阻塞IO)

NIO的特性就是同步非阻塞IO模型

优势:

使用nio解决了使用BIO服务端创建过多子线程产生内存不足, 这么多的子线程也需要进行调度, 切换, 销毁也是非常消耗性能的问题

问题解决:

package com.mcc.bio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;


public class MyNioServer {
    public static void main(String[] args) {
        try {
            //1.开启ServerSocketChannel管道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //2.设置为非阻塞
            serverSocketChannel.configureBlocking(false);
            //3.绑定ip与port
            serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 9999));
            //4.将ServerSocketChannel注册到Selector选择器中
            
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            while(true){
                //5.获取管道的状态, 没有状态阻塞
                selector.select();
                //6.获取所有事件的迭代器
                Set selectionKeys = selector.selectedKeys();
                Iterator iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    //7.获取迭代器中的每一个状态
                    SelectionKey next = iterator.next();
                    //8.状态为成功接收到客户端时
                    if(next.isAcceptable()){
                        //9.接收客户端的连接
                        SocketChannel accept = serverSocketChannel.accept();
                        System.out.println("接收到了客户端的连接");
                        //10.设置为非阻塞
                        accept.configureBlocking(false);
                        //11.监听数据的读取状态(接收到消息时, 为该状态)
                        accept.register(selector, SelectionKey.OP_READ);
                    }
                    if(next.isReadable()){
                        
                        //12.获取客户端管道
                        SocketChannel socketChannel = (SocketChannel) next.channel();
                        //13.读取客户端发送的消息
                        ByteBuffer allocate = ByteBuffer.allocate(1024);
                        socketChannel.read(allocate);
                        byte[] array = allocate.array();
                        System.out.println(new String(array, 0, allocate.position()));
                        
                        socketChannel.write(ByteBuffer.wrap("在吗?".getBytes()));
                    }
                    //移除当前的事件防止重复处理
                    iterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
package com.mcc.bio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;


public class MyNioClient {
    public static void main(String[] args) throws IOException {
        try {
            //1.开启SocketChannel管道
            SocketChannel socketChannel = SocketChannel.open();
            //2.设置为非阻塞
            socketChannel.configureBlocking(false);
            //3.将管道注册到Selector(选择器)中
            
            Selector selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            //4.连接服务端
            socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
            while(true) {
                //5.获取客户端的状态(有状态, 继续执行. 没有状态, 阻塞等待)
                selector.select();
                //6.获取所有状态的迭代器
                Iterator iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    //7.获取每一个状态
                    SelectionKey next = iterator.next();
                    //8.已经与服务端连接成功状态时
                    if(next.isConnectable()){
                        //9.正在连接中
                        if (socketChannel.isConnectionPending()) {
                            //10.设置为完成连接
                            socketChannel.finishConnect();
                        }
                        System.out.println("与服务端连接成功");
                        
                        socketChannel.write(ByteBuffer.wrap("客户端连接成功".getBytes()));
                        //12.监听读取的事件(服务端发送消息会被监听到)
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    if(next.isReadable()){
                        
                        ByteBuffer allocate = ByteBuffer.allocate(1024);
                        socketChannel.read(allocate);
                        byte[] array = allocate.array();
                        System.out.println(new String(array, 0, allocate.position()));
                        
                        socketChannel.write(ByteBuffer.wrap("在".getBytes()));
                    }
                    //15.移除当前的事件防止重复处理
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/877997.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号