Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >BIO和伪异步IO

BIO和伪异步IO

作者头像
黑洞代码
发布于 2021-01-14 07:37:05
发布于 2021-01-14 07:37:05
52800
代码可运行
举报
运行总次数:0
代码可运行

JDK1.0到JDK3.0中,Java IO类库中很多Unix网络编程中很多高级特性和接口都没有实现,如Pipe、Channel、Buffer和Selector等。

JDK1.4中,NIO以JSR-51的身份随JDK发布,其中增加了java.nio包。JDK1.7中对于原有的NIO类库进行了升级,被称为NIO2.0。

BIO通信

采用BIO模型的服务端,通常是用一个Acceptor线程监听客户端的连接,收到客户端请求后为每个客户端创建一个新的服务器端线程进行请求处理,处理完后将结果返回给客户端,销毁服务器端线程。

缺点:缺乏弹性伸缩能力。当客户端并发上升,服务器端线程会跟客户端线程成1:1的关系,导致服务端系统性能下降,最终导致系统宕机或奔溃。

BIO客户端

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BioClient {
    public static void main(String[] args) {
        int port = 8888;
        Socket socket = null;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            socket = 
            new Socket("127.0.0.1", port);
            in = new BufferedReader(
                new InputStreamReader(
                    socket.getInputStream()));
            out = new PrintWriter(
                socket.getOutputStream()
                , true);
            out.println("hello world");
            String resp = in.readLine();
            System.out.println(resp);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

BIO服务端

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BioServer {

    public static void main(String[] args) {
        int port = 8888;
        ServerSocket serverSocket = null;
        try {
            serverSocket 
                = new ServerSocket(port);
            System.out.println("端口8888启动");
            Socket socket = null;
            while (true) {
             socket = serverSocket.accept();
             new Thread(
                new ServerHandler(socket))
                .start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null) {
                System.out.println("关闭服务端");
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

BIO处理线程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ServerHandler implements Runnable {
    private Socket socket;

    public ServerHandler (Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            in = new BufferedReader(
                new InputStreamReader(
                  this.socket
                    .getInputStream()));
            out = new PrintWriter(
                    this.socket
                    .getOutputStream(), true);
            String current = null;
            String body = null;
            while (true) {
                body = in.readLine();
                if (body == null) {
                    break;
                }
                System.out.println(
                    "获取客户端输入:" + body);
                out.println(
                  "当前时间是:" + new Date());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                out.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

伪异步IO

既然BIO会为每个客户端在服务器端生成一个处理线程,服务器端可以用来做优化。当有新的客户端接入时,将客户端socket封装成一个任务,提交到线程池去执行。由于线程池有一系列参数(核心线程,最大线程,阻塞队列)约束,因此线程池占用的资源是可控的,即无论多少客户端连接到服务器端,都不会导致服务器资源耗尽而宕机。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class FakeNioServer {

    public static void main(String[] args) {
        int port = 8888;
        ServerSocket serverSocket = null;
        ExecutorService executorService = null;
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("服务器端口8888启动");
            Socket socket = null;
            executorService = Executors
            .newFixedThreadPool(10);
            while (true) {
                socket 
                    = serverSocket.accept();
                executorService
                    .submit(
                    new ServerHandler(socket));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null) {
                System.out.println("关闭服务端");
                try {
                    serverSocket.close();
                    executorService.shutdown();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

虽然伪异步IO避免了为每个客户端创建线程,但是因其底层通信仍然是同步阻塞模型,因此没有从根本是解决这个问题。

看下BIO中的InputStream的源码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Reads the next byte of data from the input stream. The value byte is
 * returned as an <code>int</code> in the range <code>0</code> to
 * <code>255</code>. If no byte is available because the end of the stream
 * has been reached, the value <code>-1</code> is returned. This method
 * blocks until input data is available, the end of the stream is detected,
 * or an exception is thrown.
 *
 * <p> A subclass must provide an implementation of this method.
 *
 * @return     the next byte of data, or <code>-1</code> if the end of the
 *             stream is reached.
 * @exception  IOException  if an I/O error occurs.
 */
public abstract int read() throws IOException;

当对socket的输入流进行读操作时,他会一直阻塞住,直到发生以下三种事件:

1.有数据可读

2.可读数据已经读取完毕

3.抛出异常

如果发送数据的一方处理速度缓慢,需要1分钟才能把数据发送完成,数据读取方必须同步阻塞1分钟。

对于BIO中的输出流也是会阻塞。

当数据接收方处理缓慢的时候,由于其不能及时的从TCP缓冲区读取数据,导致数据发送方的TCP window size不断减小,直到为0 ,双方处于Keep-Alive状态,此时消息发送方将不能再向缓冲区写入数据,write操作被无限期阻塞,直到window size大于0或者发生IO异常。

如何解决BIO带来的这些缺点呢?

Java中的NIO将解决这些问题

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 落叶飞翔的蜗牛 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面试刷题11:java系统中io的分类有哪些?
    随着分布式技术的普及和海量数据的增长,io的能力越来越重要,java提供的io模块提供了足够的扩展性来适应。 我是李福春,我在准备面试,今天的问题是: java中的io有哪几种? java中的io分3类: 1,BIO ,即同步阻塞IO,对应java.io包提供的工具;基于流模型,虽然直观,代码实现也简单,但是扩展性差,消耗资源大,容易成为系统的瓶颈; 2,NIO,同步非阻塞io,对应java.nio包提供的工具,基于io多路复用; 核心类:Channel ,Selector , Buffer , Charset selector是io多路复用的基础,实现了一个线程高效管理多个客户端连接,通过事件监听处理感兴趣的事件。 3,AIO,即异步非阻塞io, 基于事件和回调
李福春
2025/07/01
550
面试刷题11:java系统中io的分类有哪些?
阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一锅端
本文会涉及到阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO等几个知识点,知识点虽然不难但经常容易搞混,这次带领大家再回顾一遍。
码农编程进阶笔记
2021/07/20
4330
阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一锅端
Netty 之传统 BIO、NIO 编程
系列文章:http://www.jianshu.com/p/594441fb9c9e
Yano_nankai
2018/10/08
4290
原来传统BIO的局限性在这里!
大家都知道传统的 BIO 网络模型有各种各样的缺点,于是就有了关于 NIO 网络模型的出现,更多的人也都开始喜欢使用 Netty 这种框架来进行开发,而摒弃了传统的 BIO 的模型,今天阿粉就给大家说一下为什么这么多人对 BIO 网络模型这么的头疼。
Java极客技术
2022/12/02
2740
原来传统BIO的局限性在这里!
Netty序章之BIO NIO AIO演变
Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能、高可靠的网络服务器和客户端程序。Netty简化了网络程序的开发,是很多框架和公司都在使用的技术。更是面试的加分项。Netty并非横空出世,它是在BIO,NIO,AIO演变中的产物,是一种NIO框架。而BIO,NIO,AIO更是笔试中要考,面试中要问的技术。也是一个很好的加分项,加分就是加工资,你还在等什么?本章带你细细品味三者的不同! 流程图:
用户1212940
2022/04/13
5660
Netty序章之BIO NIO AIO演变
Bio、Nio、Aio的用法系列之BIO(一)
上面我们开始监听8888端口,启动这个main后,肯定阻塞到accept,等待客户端发送过来消息
用户1257393
2018/07/30
3860
浅谈Java BIO 和 NIO
Socket 是什么呢,其实就是一个 有 IP地址+端口,并且持有文件描述符的对象,操作系统通过 ip + port 建立 TCP 连接;通过文件描述符来读取传输的数据。无论操作系统内核,还是JDK,都会定义一个Socket的数据结构。
搬砖俱乐部
2020/03/20
5140
netty是如何一步一步演化而来的,不断进化成就netty
-多路复用器。这里我们可以理解为注册中心。所有的handler再向selector注册的时候会带上标签(SelectorKey)。在某个Channel发生读或写的事件时这个Channel会处于就绪状态。在Selector轮询的时候会筛选出来。然后我们在根据SelectorKey判断监听的是什么事件。从而做出处理。查阅资料得知selector没有连接限制。理论上一个selector可以管理N个Channel。
啵啵肠
2023/11/28
2070
Netty基础—2.网络编程基础二
既然是通信,那么肯定会有两个对端。在网络编程里提供服务的一方叫服务端,连接服务端使用服务的另一方叫客户端。
东阳马生架构
2025/05/16
710
JavaIO流:BIO梳理
Java BIO 就是传统的 java io 编程,其相关的类和接口在 java.io
栗筝i
2022/12/02
6250
JavaIO流:BIO梳理
Java网络编程之BIO
作为一个WEB程序员,网络编程模型是我们需要掌握的基础知识,在介绍具体模型之前先聊下几个基本的概念:
心平气和
2021/03/16
3950
02-Java BIO编程
在调用的过程中,我们的main主线程用于监听客户端的连接, 每次在在accept方法出阻塞,等待,在有客户端连接的时候通过线程池创建一个新的线程用于处理当前的客户端连接,而main线程继续循环阻塞在accept方法
彼岸舞
2022/02/18
3210
02-Java BIO编程
BIO NIO AIO演变1 BIO2 NIO3 AIO4 常见面试题5 总结
Block-IO 是一种阻塞同步的通信模式。 常说的Socket IO 一般指的是BIO。是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。
JavaEdge
2018/08/10
1.4K0
BIO NIO AIO演变1 BIO2 NIO3  AIO4 常见面试题5  总结
BIO、NIO、AIO原理及总结
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销。
用户5325874
2020/04/13
8610
Java网络编程--BIO阻塞式网络编程
阻塞(blocking)IO :阻塞是指结果返回之前,线程会被挂起,函数只有在得到结果之后(或超时)才会返回
CodingDiray
2019/09/25
1K0
Java网络编程--BIO阻塞式网络编程
【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )
① 异步 : 与同步相对 , 操作之间 不产生阻塞 , 发出请求后可以不等待回应 , 继续执行后面的代码逻辑 ;
韩曙亮
2023/03/27
5730
【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )
Java核心(五)深入理解BIO、NIO、AIO
导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别;BIO、NIO、AIO 的区别;理解和实现 NIO 操作 Socket 时的多路复用;同时掌握 IO 最底层最核心的操作技巧。
磊哥
2018/12/24
7160
传统的BIO
网络编程的基本模型是C/S模型(client/server),即两个进程间的通信。
田维常
2019/10/11
5960
传统的BIO
一文了解Java的IO模型
我们都知道在 Java 当中有许许多多的使用上的问题,比如 Java 的锁,Java 的安全性,以及 Java 的IO操作,Java 中各种设计模式的使用,今天我们就来说说关于这个 Java 的IO。
Java极客技术
2024/01/31
7700
一文了解Java的IO模型
Java IO: BIO, NIO, AIO
BIO, NIO, AIO,本身的描述都是在Java语言的基础上的。 而描述IO,我们需要从三个层面:
九州暮云
2019/08/21
7210
相关推荐
面试刷题11:java系统中io的分类有哪些?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验