BIO & NIO

作者: AC编程 | 来源:发表于2020-08-22 09:04 被阅读0次

    一、用单线程来优化不活跃线程较多的情况

    BIO等待连接时需要阻塞,等待接收客户端发送数据时也需要阻塞。如果有一个客户端连接了服务端,但一直不发送消息,服务端就一直阻塞等待接收客户端的消息,无法接收其他客户端的连接。因此,如果不用多线程,BIO无法处理并发。

    但加入多线程处理并发有一个弊端,如有1000个客户端来连服务端,服务端就需要开启1000个线程来处理客户端的数据,但1000个连接里只有100个连接是活跃连接,另外900个只连接不发送消息,那这900个线程就是浪费。因此,当服务器端不活跃的线程比较多时,要用单线程的方案来优化。

    二、代码演示

    2.1 IO客户端代码
    import java.net.Socket;
    import java.util.Scanner;
    
    /**
     * @author Alan Chen
     * @description IO测试
     * @date 2020/8/22
     */
    public class Client {
    
        public static void main(String[] args) throws Exception {
            Socket socket = new Socket("127.0.0.1", 8080);
    
            //socket.getOutputStream().write("alanchen".getBytes());
    
            // 体现服务端read是阻塞的,要等客户端发送数据
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入内容:");
            while (true){
                String next = scanner.next();
                socket.getOutputStream().write(next.getBytes());
            }
        }
    }
    
    2.2 BIO 代码
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * @author Alan Chen
     * @description BIO测试
     * @date 2020/8/22
     */
    public class BIOServer {
    
        static byte[] bytes = new byte[1024];
    
        public static void main(String[] args) throws Exception {
    
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(8080));
    
            while (true){
                System.out.println("等待连接");
                // 阻塞
                Socket socket = serverSocket.accept();
                System.out.println("连接成功");
    
                /**
                 * 如果有客户端连接了,但一直不发送数据,服务端就会阻塞在这里,
                 * 无法在处理其他连接,如果要实现并发,则需要开启一个子线程来接收数据
                 * 线程代码:略
                 */
                System.out.println("等待接收数据");
                //阻塞 读了多少字节
                int read = socket.getInputStream().read(bytes);
                System.out.println("数据接收成功");
    
                String content = new String(bytes);
                System.out.println(content);
            }
        }
    }
    
    2.3 NIO代码
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author Alan Chen
     * @description NIO测试
     * @date 2020/8/22
     */
    public class NIOServer {
    
        static List<SocketChannel> socketChannelList = new ArrayList<>();
        static ByteBuffer byteBuffer = ByteBuffer.allocateDirect(512);
    
        public static void main(String[] args) throws Exception {
    
            ServerSocketChannel serverSocket = ServerSocketChannel.open();
            serverSocket.bind(new InetSocketAddress(8080));
            //设置为非阻塞
            serverSocket.configureBlocking(false);
    
            while (true){
    
                SocketChannel socket = serverSocket.accept();
    
                if(socket==null){
                    Thread.sleep(1500);
                    System.out.println("没有连接请求");
                }else {
                    System.out.println("有连接请求");
                    //设置为非阻塞
                    socket.configureBlocking(false);
                    socketChannelList.add(socket);
                }
    
                /**
                 * 这种轮询的方式效率也很低,比如有1000万个连接,
                 * 但只有200万个是活跃的,每次都沦陷另外800万个连接,也是一种资源浪费,
                 * 解决方案是用epoll
                 */
                for(SocketChannel socketChannel : socketChannelList){
                    int k = socketChannel.read(byteBuffer);
                    if(k>0){
                        byteBuffer.flip();
                        System.out.println(Charset.forName("utf-8").decode(byteBuffer));
                    }
                }
    
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:BIO & NIO

          本文链接:https://www.haomeiwen.com/subject/rbxsjktx.html