BIO的流程以及问题

BIO:

原生的Java IO 模型为同步并阻塞型,传统的java io编程,其相关的类都在java.io里

同步并阻塞;
服务器实现模式为一个个连接一个线程,即客户端有连接请求时,服务端就需要启动一个线程来进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当连接或者并发量增大的时候,它是有瓶颈的.可以通过线程池机制改善(实现多个客户连接服务器).

作用场景:

程序简单 易理解,连接数少且固定的架构.

BIO的简单流程以及工作原理:

1.服务器端启动一个serverSocket
2.客服端启动Socket对服务器进行通信,默认情况下服务器端需要对每个客户建立一个线程与之通讯
3.客户端发出请求后,先咨询服务器是否有线程响应,如果没有则会等待,或者被拒绝
4.如果有响应,客户端线程会等待请求结束后,在继续执行
下面我们简单用代码实现模拟一下BIO的场景:
服务端:

package com.jym.bio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @program: JymNetty
 * @description: bio应用实例
 * @author: jym
 * @create: 2020/01/31
 */
public class BioTest {
    public static void main(String[] args) throws IOException {
        // 创建线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();
        // 创建serverSocket
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器启动了");
        while (true){
            // 监听 等待用户连接  如果没有用户连接,就会阻塞
            System.out.println("等待连接.....");
            final Socket accept = serverSocket.accept();
            System.out.println("连接到一个用户");
            // 新建一个线程 与之通讯
            threadPool.execute(new Runnable() {
                public void run() {
                    handler(accept);
                }
            });
        }


    }

    // 编写一个handler方法,和客户端通讯
    public static void handler(Socket socket){
        byte[] bytes = new byte[1024];
        // 通过socket获取输入流
        try {
            InputStream inputStream = socket.getInputStream();
            while (true){
                // 如果用户什么都没发送,也会阻塞
                System.out.println("等待用户发送数据....");
                int read = inputStream.read(bytes);
                if(read!=-1){
                    // 输出客户端发送的数据
                    System.out.println(Thread.currentThread().getName()+"发送的消息为:"+new String(bytes,0,read));
                } else {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("关闭和client的连接");
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端我们就不编写代码了,直接用telnet命令发送数据
telnet命令使用之前 一定要启动我们的服务端
打开命令行窗口:
win+r 输入cmd
然后输入 telnet 127.0.0.1 6666 然后回车
如果提示说没有telnet命令,则需要开启,具体步骤为:
BIO的流程以及问题_第1张图片

BIO的流程以及问题_第2张图片
使用telnet命令后,弹出一个新窗口,输入ctrl+],就可以发送信息了
然后命令行输入 send 接上发送的信息,服务端控制台上就会打印出信息
BIO的流程以及问题_第3张图片
接下来我们再启一个telnet窗口 发送消息,观察控制台发现
BIO的流程以及问题_第4张图片
两个窗口发送信息,线程名不一样,说明每次通讯BIO都会创建一个新的线程,不管线程工不工作
BIO执行流程图:
BIO的流程以及问题_第5张图片
经过模拟的场景还有执行的流程图发现BIO有很大的问题:
1.每个请求都需要创建一个线程,与对应的客户端进行数据read,业务处理,write
2.当并发量较大时,需要创建大量的线程来处理连接,系统资源占用较大
3.连接建立后,如果线程暂时没有数据可读,则线程就阻塞在Read上,造成线程资源的浪费,如果没有用户通讯,线程就会堵塞在accept上。

学习年限不足,知识过浅,说的不对请见谅。

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

你可能感兴趣的:(Netty)