netty专栏-bio/nio/aio

前言

由于部门业务调整,以下是学习java相关内容

本文参考哔哩哔哩 2021金三银四面试精选200集

一、BIO

bio,即blocking I/O,在服务器同一线程内,接受请求与处理请求需要阻塞进行,只有在处理完一个请求之后,才会继续处理下一个请求。

在bio服务器下,可以采用线程池的方式使得服务器并发处理多个请求,但采用这种方式的服务器并发请求量有限。

示例代码1:

package BIO;

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

public class bioLearn {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9000);
        while (true) {
            System.out.println("等待连接");
            Socket socket = serverSocket.accept();
            handler(socket);
        }
    }

    public static void handler(Socket socket) throws IOException {
        System.out.println("begin read..");
        byte[] dataByte = new byte[1024];
        InputStream inputStream = socket.getInputStream();
        int readLen = inputStream.read(dataByte);
        System.out.println("read end...");
        if (readLen >= 0) {
            System.out.println("read data:" + new String(dataByte, 0, readLen));
        }
    }

}

二、NIO

nio,即non-blocking,在服务器统一线程内,接受请求与处理请求非阻塞执行。

示例代码2:

package NIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

public class NIO {
    private static List serverChannelList = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        // 创建nio
        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        // 设置
        socketChannel.socket().bind(new InetSocketAddress(9000));
        socketChannel.configureBlocking(false);
        // 接受客户端请求
        while (true) {
            SocketChannel serverSocketChannel = socketChannel.accept();
            handler(serverSocketChannel);
        }

    }

    public static void handler(SocketChannel serverSocketChannel) throws IOException {
        // 将有数据的加入列表中
        if (serverSocketChannel != null) {
            // 设置为false,则在接受连接之后,不会阻塞
            serverSocketChannel.configureBlocking(false);
            serverChannelList.add(serverSocketChannel);
        }
        // 处理数据
        for (SocketChannel serverChannel : serverChannelList) {
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int len = serverChannel.read(buffer);
            if (len > 0) {
                System.out.println("get data:" + new String(buffer.array()));
            } else {
            }
        }
    }
}

示例代码2存在两个问题,一是空转,程序会不停的查询是否有请求过来,消耗cpu资源;二是请求列表serverChannelList中,大部分请求可能没有数据,而处理数据的循环每一次都会将列表遍历一遍,当请求增多时,响应速度会变慢。

基于问题2,java引入了Selector,流程图如下

netty专栏-bio/nio/aio_第1张图片

以下是修改后的示例代码3

实例代码3

package classLearn.part1_nioBioAioLearn.NioWithSelector;

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 NioWithSelector {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(9000));
        serverSocketChannel.configureBlocking(false);
        // 打开selector
        Selector selector = Selector.open();
        // 打开selectionKey
        SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务启动成功");
        while (true) {
            // 阻塞等待需要处理的事件发生
            selector.select();
            System.out.println("事件出现");
            Set selectionKeys = selector.selectedKeys();
            Iterator selectIter = selectionKeys.iterator();
            while (selectIter.hasNext()) {
                SelectionKey key = selectIter.next();
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = server.accept();
                    socketChannel.configureBlocking(false);
                    SelectionKey readKey = socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("建立连接");
                } else if (key.isReadable()) {
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    socketChannel.configureBlocking(false);
                    int len = socketChannel.read(byteBuffer);
                    if (len > 0) {
                        System.out.println("获取数据:" + new String(byteBuffer.array()));
                    }
                }
                selectIter.remove();
            }
        }
    }
}

三、nio原理-epoll

 

你可能感兴趣的:(java)