Java BIO详解
一、简介
1.1 BIO概述
BIO(Blocking I/O),即同步阻塞IO(传统IO)。
BIO 全称是 Blocking IO,同步阻塞式IO,是JDK1.4之前的传统IO模型,就是传统的 java.io 包下面的代码实现。
服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如下图所示:
在 BIO 模型下,应用程序会在进行 I/O 操作时阻塞当前线程,直到 I/O 操作完成。例如,执行一个读取操作时,线程会等待,直到数据从磁盘或网络中完全读取完成。在这个过程中,线程不能做其他任务,必须等待 I/O 操作的结果。
BIO 模型的特点
- 同步阻塞:
- 当线程进行 I/O 操作时,它会被阻塞,直到操作完成。
- 阻塞操作通常会导致 CPU 的浪费,因为线程在等待 I/O 时并没有进行其他有用的工作。
- 一个连接一个线程:
- 每个客户端请求都会创建一个新的线程,每个线程对应一个 I/O 操作。
- 当并发连接数很多时,系统可能会因为线程数过多而导致性能瓶颈。
- 适用于连接数较少的场景:BIO 更适用于连接数较少、请求不频繁的应用场景,如一些小型应用或传统的阻塞式通信。
- 容易实现:相对于其他 I/O 模型(如 NIO 和 AIO),BIO 的实现比较简单,应用开发人员只需要关心 I/O 操作,不需要处理复杂的事件驱动机制。
BIO 的缺点:
- 线程资源浪费:每个连接都会对应一个独立的线程,当有大量并发连接时,会导致系统开销巨大,因为操作系统会为每个线程分配资源(如内存、栈空间等)。如果并发请求量很大,线程上下文切换开销也会非常高。
- 不适合高并发:BIO 模型非常依赖操作系统线程,线程数过多时容易造成系统性能下降。特别是在高并发的情况下,线程的创建和销毁频繁,容易耗尽系统资源。
- 效率低:在 I/O 操作过程中,线程被阻塞,无法处理其他请求,导致 CPU 的浪费。即使没有数据可读或可写,线程依然会等待,直到 I/O 完成。
1.2 IO流概述
IO流是基于流的概念,它将数据的输入和输出看作是一个连续的流。数据从一个地方流向另一个地方,流的方向可以是输入(读取数据)或输出(写入数据)。
IO流的原理是通过流的管道将数据从源头传输到目标地。源头可以是文件、网络连接、内存等,而目标地可以是文件、数据库、网络等。IO流提供了一组丰富的类和方法来实现不同类型的输入和输出操作。
IO流主要用于处理输入和输出操作,适用于以下场景:
- 文件读写:通过IO流可以读取和写入文件中的数据,如读取配置文件、写入日志等。
- 网络通信:通过IO流可以进行网络数据的传输和接收,如Socket通信、HTTP请求等。
- 数据库操作:通过IO流可以将数据读取到内存中,或将内存中的数据写入到数据库中。
- 文本处理:通过IO流可以读取和写入文本文件,进行文本处理和操作。
1.2.1 IO流分类
Java中的IO流可以按照数据的类型和流的方向进行分类:
- 按数据类型分类
- 字节流(Byte Stream):以字节为单位读写数据,适用于处理二进制数据,如图像、音频、视频等。常见的字节流类有InputStream和OutputStream。
- 字符流(Character Stream):以字符为单位读写数据,适用于处理文本数据。字符流会自动进行字符编码和解码,可以处理多国语言字符。常见的字符流类有Reader和Writer。
- 按流的方向分类
- 输入流(Input Stream):用于读取数据。输入流从数据源读取数据,如文件、网络连接等。常见的输入流类有FileInputStream、ByteArrayInputStream、SocketInputStream等。
- 输出流(Output Stream):用于写入数据。输出流将数据写入到目标地,如文件、数据库、网络等。常见的输出流类有FileOutputStream、ByteArrayOutputStream、SocketOutputStream等。
1.2.1.1 字符流
- 只用来处理文本数据 ;
- 数据最常见的表现形式是文件,字符流用来操作文件的子类一般是 FileReader 和 FileWriter 。
字符流读写文件注意事项:
- 写入文件必须要用 flush() 刷新 ;
- 用完流记得要关闭流 ;
- 使用流对象要抛出IO异常 ;
- 定义文件路径时,可以用"/"或者"\" ;
- 在创建一个文件时,如果目录下有同名文件将被覆盖 ;
- 在读取文件时,必须保证该文件已存在,否则抛出异常 ;
- 字符流的缓冲区 ;
- 缓冲区的出现是为了提高流的操作效率而出现的 ;
- 需要被提高效率的流作为参数传递给缓冲区的构造函数 ;
- 在缓冲区中封装了一个数组,存入数据后一次取出 。
1.2.1.2 字节流
- 用来处理媒体数据 。
字节流读写文件注意事项:
- 字节流和字符流的基本操作是相同的,但是想要操作媒体流就需要用到字节流 ;
- 字节流因为操作的是字节,所以可以用来操作媒体文件(媒体文件也是以字节存储的);
- 输入流(InputStream)、输出流(OutputStream);
- 字节流操作可以不用刷新流操作 ;
- InputStream特有方法:int available()(返回文件中的字节数);
- 字节流的缓冲区 ;
- 字节流缓冲区跟字符流缓冲区一样,也是为了提高效率 。
1.2.2 常用IO流
1.2.2.1 字节输入流类
- InputStream:用于从输入源读取字节数据的抽象类。
- FileInputStream:从文件中读取字节数据的类。
- ByteArrayInputStream:从字节数组中读取字节数据的类。
- BufferedInputStream:提供缓冲功能的字节输入流类。
- DataInputStream:读取基本数据类型的字节输入流类。
try (InputStream is = new FileInputStream("input.txt");BufferedInputStream bis = new BufferedInputStream(is)) {int data;while ((data = bis.read()) != -1) {System.out.print((char) data);}
} catch (IOException e) {e.printStackTrace();
}
1.2.2.2 字符输入流类
- Reader:用于从输入源读取字符数据的抽象类。
- FileReader:从文件中读取字符数据的类。
- BufferedReader:提供缓冲功能的字符输入流类。
- InputStreamReader:将字节流转换为字符流的类。
try (Reader reader = new FileReader("input.txt");BufferedReader br = new BufferedReader(reader)) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}
} catch (IOException e) {e.printStackTrace();
}
1.2.2.3 字节输出流类
- OutputStream:用于向输出目标写入字节数据的抽象类。
- FileOutputStream:将字节数据写入文件的类。
- ByteArrayOutputStream:将字节数据写入字节数组的类。
- BufferedOutputStream:提供缓冲功能的字节输出流类。
- DataOutputStream:将基本数据类型写入输出流的类。
try (OutputStream os = new FileOutputStream("output.txt");BufferedOutputStream bos = new BufferedOutputStream(os)) {String data = "Hello, World!";bos.write(data.getBytes());
} catch (IOException e) {e.printStackTrace();
}
1.2.2.4 字符输出流类
- Writer:用于向输出目标写入字符数据的抽象类。
- FileWriter:将字符数据写入文件的类。
- BufferedWriter:提供缓冲功能的字符输出流类。
- OutputStreamWriter:将字节流转换为字符流的类。
try (Writer writer = new FileWriter("output.txt");BufferedWriter bw = new BufferedWriter(writer)) {String data = "Hello, World!";bw.write(data);
} catch (IOException e) {e.printStackTrace();
}
1.2.3 Java Scanner类
Java 5添加了 java.util.Scanner 类,这是一个用于扫描输入文本的新的实用程序。
- 关于 nextInt()、next()、nextLine() 的理解 :
- nextInt() :只能读取数值,若是格式不对,会抛出 java.util.InputMismatchException 异常 ;
- next() :遇见第一个有效字符(非空格,非换行符)时,开始扫描,当遇见第一个分隔符或结束符(空格或换行符)时,结束扫描,获取扫描到的内容 ;
- nextLine() :可以扫描到一行内容并作为字符串而被捕获到 。
- 关于 hasNext()、hasNextLine()、hasNextxxx() 的理解 :就是为了判断输入行中是否还存在xxx的意思。
- 与 delimiter() 有关的方法的理解 :应该是输入内容的分隔符设置,
二、BIO工作机制
客户端:
- 通过Socket对象请求与服务端建立连接。
- 从Socket中得到字节输入或者字节输出流进行数据读写操作。
服务端:
- 通过ServerSocket注册端口。
- 服务端通过调用accept方法用于监听客户端的Socket请求。
- 从Socket中得到字节输入或者字节输出流进行数据读写操作。
三、简单编码实现
3.1 服务端
public class BioServer {public static void main(String[] args) {ServerSocket serverSocket = null;try {serverSocket = new ServerSocket(8080);System.out.println("Server is listening on port 8080...");while (true) {// 阻塞等待客户端连接Socket clientSocket = serverSocket.accept();System.out.println("Client connected: " + clientSocket.getInetAddress());// 为每个客户端请求创建一个新线程进行处理new Thread(new ClientHandler(clientSocket)).start();}} catch (IOException e) {e.printStackTrace();} finally {try {if(serverSocket != null){serverSocket.close();}} catch (IOException e){e.printStackTrace();}}}
}class ClientHandler implements Runnable {private Socket socket;public ClientHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {BufferedInputStream bufferedInputStream = null;BufferedOutputStream bufferedOutputStream = null;try {bufferedInputStream = new BufferedInputStream(socket.getInputStream());;bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());System.out.println("收到来自客户端的消息:");byte[] bytes = new byte[1024]; //创建字节数组,存储临时读取的数据int len ; //记录数据读取的长度if ((len = bufferedInputStream.read(bytes)) > -1) { //长度为-1则读取完毕String result = new String(bytes,0,len);System.out.println(result);}String outString = "服务端收到,这里是线程" + Thread.currentThread().getName();System.out.println("回复信息给客户端: " + outString);bufferedOutputStream.write(outString.getBytes());bufferedOutputStream.flush();System.out.println("回复完成========");} catch (IOException e) {e.printStackTrace();} finally {System.out.println("关闭数据流========");try {if (bufferedInputStream != null) {bufferedInputStream.close();}if (bufferedOutputStream != null) {bufferedOutputStream.close();}} catch (IOException e){e.printStackTrace();}}}
}
工作过程:
- 服务器通过 ServerSocket 对象监听 8080 端口,等待客户端连接。
- 每当有一个客户端连接到服务器时,serverSocket.accept() 会阻塞当前线程,直到有客户端连接进来。
- 然后,服务器会为每个客户端连接创建一个新线程来处理该客户端的请求。
- 线程通过 BufferedInputStream 读取客户端发送的数据,并通过 BufferedOutputStream 回复客户端。
3.2 客户端
public class BioClient {public static void start() throws IOException {Socket socket = new Socket("127.0.0.1", 8080);String msg = "Hi,This is the BioClient";byte[] msgBytes = msg.getBytes();//1.拿到输出流//2.对输出流进行处理BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());//3.输出msgbufferedOutputStream.write(msgBytes);bufferedOutputStream.flush();System.out.println("客户端发送消息完毕: " + msg);System.out.println("客户端开始接收到消息==========");//4.对输入流进行处理BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());System.out.println("客户端接收到的消息:");byte[] inBytes = new byte[1024];int len;//5.读取输入流if ((len = bufferedInputStream.read(inBytes)) != -1) {String result = new String(inBytes, 0, len);System.out.println(result);}//6.关闭输入输出流bufferedOutputStream.close();bufferedInputStream.close();socket.close();}public static void main(String[] args) throws IOException {start();}
}
工作过程:
- 与服务端建立连接
- 发送消息给服务端
- 接收服务端返回的消息
相关文章:

Java BIO详解
一、简介 1.1 BIO概述 BIO(Blocking I/O),即同步阻塞IO(传统IO)。 BIO 全称是 Blocking IO,同步阻塞式IO,是JDK1.4之前的传统IO模型,就是传统的 java.io 包下面的代码实现。 服务…...
统计满足条件的4位数(信息学奥赛一本通-1077)
【题目描述】 给定若干个四位数,求出其中满足以下条件的数的个数:个位数上的数字减去千位数上的数字,再减去百位数上的数字,再减去十位数上的数字的结果大于零。 【输入】 输入为两行,第一行为四位数的个数n࿰…...
北京门头沟区房屋轮廓shp的arcgis数据建筑物轮廓无偏移坐标测评
在IT行业中,地理信息系统(GIS)是用于处理、分析和展示地理空间数据的重要工具,而ArcGIS则是GIS领域中的一款知名软件。本文将详细解析标题和描述中提及的知识点,并结合“门头沟区建筑物数据”这一标签,深入…...
Spring 面试题【每日20道】【其三】
1、Spring 中的 Profile 注解的作用是什么? 中等 Profile 注解在Spring框架中用于根据不同的环境配置文件(profiles)来激活或忽略某些Bean的注册。它允许开发者定义逻辑以区分不同环境下的bean定义,例如开发、测试和生产环境。 …...

FFmpeg(7.1版本)在Ubuntu18.04上的编译
一、从官网上下载FFmpeg源码 官网地址:Download FFmpeg 点击Download Source Code 下载源码到本地电脑上 二、解压包 tar -xvf ffmpeg-7.1.tar.xz 三、配置configure 1.准备工作 安装编译支持的软件 ① sudo apt-get install nasm //常用的汇编器,用于编译某些需要汇编…...
Apache Hudi数据湖技术应用在网络打车系统中的系统架构设计、软硬件配置、软件技术栈、具体实现流程和关键代码
网络打车系统利用Hudi数据湖技术成功地解决了其大规模数据处理和分析的难题,提高了数据处理效率和准确性,为公司的业务发展提供了有力的支持。 Apache Hudi数据湖技术的一个典型应用案例是网络打车系统的数据处理场景,具体如下: 大…...

安全策略配置
需求: 1、VLAN 2属于办公区;VLAN 3属于生产区 2、办公区PC在工作日时间(周一至周五,早8到晚6)可以正常访问0A Server,其他时间不允许 3、办公区PC可以在任意时刻访问web server 4、生产区PC可以在任意时刻访问0A Server,但是不能访问Web serv…...
c++ stl 遍历算法和查找算法
概述: 算法主要由头文件<algorithm> <functional> <numeric> 提供 <algorithm> 是所有 STL 头文件中最大的一个,提供了超过 90 个支持各种各样算法的函数,包括排序、合并、搜索、去重、分解、遍历、数值交换、拷贝和…...

【Envi遥感图像处理】008:波段(批量)分离与波段合成
文章目录 一、波段分离提取1. 提取单个波段2. 批量提取单个波段二、波段合成相关阅读:【ArcGIS微课1000例】0058:波段合成(CompositeBands)工具的使用 一、波段分离提取 1. 提取单个波段...
线程创建与管理 - 创建线程、线程同步(C++)
前言 在现代软件开发中,线程的创建和管理是并发编程的核心内容之一。通过合理地创建和管理线程,可以有效提高程序的响应速度和资源利用率。本文将详细讲解如何在C中创建线程,并探讨几种常见的线程同步机制。我们假设读者具备一定的C基础&…...

【C语言篇】“三子棋”
一、游戏介绍 三子棋,英文名为 Tic - Tac - Toe,是一款简单而经典的棋类游戏。游戏在一个 33 的棋盘上进行,两名玩家轮流在棋盘的空位上放置自己的棋子(通常用 * 和 # 表示),率先在横、竖或斜方向上连成三个…...

安培定律应用于 BH 曲线上的工作点
在本篇博文中,我将展示如何应用安培定律来确定磁芯包裹的导体必须承载多少电流才能从 BH 值工作点获得 B 值,该工作点对应于磁芯材料中的最大 B 值。我在 BH 曲线上使用两个工作点,一个在线性区域,另一个在饱和区域。 安培定律 H…...

深度求索DeepSeek横空出世
真正的强者从来不是无所不能,而是尽我所能。多少有关输赢胜负的缠斗,都是直面本心的搏击。所有令人骄傲振奋的突破和成就,看似云淡风轻寥寥数语,背后都是数不尽的焚膏继晷、汗流浃背。每一次何去何从的困惑,都可能通向…...
【CSS】什么是响应式设计?响应式设计的基本原理,怎么做
在当今多设备、多屏幕尺寸的时代,网页设计面临着前所未有的挑战。传统的固定布局已无法满足用户在不同设备上浏览网页的需求,响应式设计(Responsive Web Design)应运而生,成为网页设计的趋势和标准。本文将深入探讨响应…...

后盾人JS--继承
继承是原型的继承 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </hea…...
提升开发效率:IDE使用技巧与插件推荐
在软件开发过程中,选择一个合适的集成开发环境(IDE)并掌握其使用技巧,可以显著提高开发效率。本文将分享一些常用的IDE使用技巧,并推荐几款实用的插件,帮助开发者更好地利用IDE进行开发。 一、IDE使用技巧…...
开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B与vllm实现推理加速的正确姿势(一)
一、前言 在当今人工智能技术迅猛发展的时代,各类人工智能模型如雨后春笋般不断涌现,其性能的优劣直接影响着应用的广度与深度。从自然语言处理到计算机视觉,从智能安防到医疗诊断,AI 模型广泛应用于各个领域,人们对其准确性、稳定性和高效性的期望也与日俱增。 在此背景下…...

小书包:让阅读更美的二次开发之作
小书包是在一款知名阅读软件的基础上进行二次开发的产品。在保留原有软件的基本功能和用户体验的同时,对其界面和视觉效果进行了精心美化,让阅读体验更加舒适和愉悦。 内置了171条书源,虽然数量不算多,但都是作者精挑细选出来的&a…...
MySQL 插入数据指南
MySQL 插入数据指南 引言 MySQL 是一款广泛使用的开源关系数据库管理系统,被广泛应用于各种规模的组织中。在数据库管理中,数据的插入是基础操作之一。本文将详细介绍如何在 MySQL 中插入数据,包括插入单条记录和多条记录,以及一…...

防火墙安全策略实验
一、拓扑图 需求 Cloud云: 二、防火墙配置 初始化防火墙 Username:admin Password:***** The password needs to be changed. Change now? [Y/N]: y Please enter old password: Admin123 Please enter new password: admin123 Please confirm new password: …...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...