BIO&NIO&AIO

IO模型

java共支持3中IO模型:BIO,NIO,AIO。下面来总结一下三种模型。

BIO

BIO(Blocking IO): 同步阻塞IO。

代码

public static void main(String[] args) throws Exception {
    ServerSocket serverSocket = new ServerSocket(9000);

    System.out.println("BIOServer等待连接。。");
    //阻塞方法   等待客户端的链接
    Socket clientSocket = serverSocket.accept();
    System.out.println("BIOServer有客户端连接了。。");
    
    byte[] bytes = new byte[1024];
    System.out.println("准备read。。");
    //阻塞方法  等待客户端写数据,没有数据可读时就阻塞
    int read = clientSocket.getInputStream().read(bytes);
    System.out.println("read完毕。。");
    if (read != -1) {
        System.out.println("接收到客户端的数据:" + new String(bytes, 0, read));
    }
    clientSocket.getOutputStream().write("HelloClient".getBytes());
    clientSocket.getOutputStream().flush();


}

上述代码中,serverSocket.accept()和clientSocket.getInputStream().read(bytes)方法是阻塞的,如果多个客服端线程来连接服务端,就会造成阻塞,降低性能。如果使用多线程来解决性能问题,来多少个客户端开多少个线程,显然是不合适的,服务端压力也会加大。因此,BIO会有以下缺点:

  1. IO代码里的accept和read操作是阻塞操作,会造成线程阻塞,浪费资源;
  2. 如果线程过多,会导致服务端压力过大。

NIO

NIO(Non Blocking IO): 同步非阻塞,从jdk1.4开始支持,主要有三大组件,channel,selector,buffer。

NIO三大组件:

  1. channel(通道)
    1. 类似于流,是双向的,一个流只可能是InputStream或是OutputStream,但是channel是双向的;
  2. selector(选择器)
    1. channel会注册到selector上,由selector根据channel的读写事件交给空闲的线程处理;
  3. buffer(缓冲区)
    1. 所有数据的读写都是通过buffer来进行的,java中的原生8种基本数据类型都有各自对应的buffer类型,(除Boolean外),如IntBuffer,CharBuffer,ByteBuffer,LongBuffer,ShortBuffer。

 

 

 

代码

public static void main(String[] args) {
    try {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false); //设置非阻塞模式
        serverSocketChannel.bind(new InetSocketAddress(9090));//绑定9090端口
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //将selector注册到serverSocketChannel
        while (true) {
            selector.select();//此方法为阻塞方法
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey selectionKey = keyIterator.next();
                if (selectionKey.isValid()) { //此键是否有效
                    if (selectionKey.isAcceptable()) {  //连接事件
                        ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel();
                        SocketChannel socketChannel = serverSocketChannel1.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    if (selectionKey.isReadable()) { //读取数据
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        socketChannel.read(buffer);
                        System.out.println(new String(buffer.array()));
                        ByteBuffer buffer1 = ByteBuffer.wrap(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()).getBytes());
                        socketChannel.write(buffer1);
                    }
                }
                keyIterator.remove();//移除key,避免重复消费
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

步骤:

  1. 开启ServerSocketChannel,绑定9090端口,并设置为非阻塞模式;
  2. 开始Selector,并将ServerSocketChannel注册到Selector,监听连接事件;
  3. 调用select()方法,是否有事件进来,如果有,则获取并遍历SelectionKey,判断其为连接事件还是读取事件,并做对应的操作,做完相应操作之后移除key,避免重复消费。

总结

NIO是基于epoll基于事件响应机制来优化NIO。Redis也是典型的基于epoll的NIO线程模型(nginx也是),epoll实例收集所有事件(连接与读写事件),由一个服务端线程连续处理所有事件

命令,所以redis目前是单线程的。

 

AIO

异步非阻塞:适用于连接数目多且连接比较长(重操作)的架构。

用法

AsynchronousServerSocketChannel与NIO中ServerSocketChannel用法基本一致,AsynchronousSocketChannel与SocketChannel用法基本一致,只不过是在CompletionHandler的回调completed方法中处理逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值