当前位置: 首页 > news >正文

Java NIO与传统IO性能对比分析

Java NIO与传统IO性能对比分析

在Java中,I/O(输入输出)操作是开发中最常见的任务之一。传统的I/O方式基于阻塞模型,而Java NIO(New I/O)引入了非阻塞和基于通道(Channel)和缓冲区(Buffer)的新方式,能够更有效地处理大量I/O操作。本文将对Java传统I/O和NIO的性能进行对比分析,并展示如何通过代码实例理解两者的差异。

传统I/O概述

传统的Java I/O库基于流(Stream)和阻塞I/O模型。在传统I/O中,所有的操作都是同步的,当读取或写入数据时,操作会阻塞,直到数据完全读写完毕。这种方式的优点是简单直观,适合处理小规模的I/O操作。然而,在面对大量并发I/O时,传统I/O的性能表现就会显得比较差,容易导致线程阻塞,造成不必要的资源浪费。

传统I/O的使用

import java.io.*;public class TraditionalIOExample {public static void main(String[] args) {try (FileInputStream fis = new FileInputStream("input.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {fos.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}}
}

在这个示例中,我们通过传统的FileInputStreamFileOutputStream读取和写入文件。fis.read(buffer)方法是阻塞的,直到读取完数据才会返回。

Java NIO概述

Java NIO(New I/O)是Java 1.4引入的一种新的I/O库,提供了对I/O的改进,尤其是针对高性能I/O和大规模并发I/O操作。NIO引入了通道(Channel)和缓冲区(Buffer)模型,并支持非阻塞I/O(Non-blocking I/O)和选择器(Selector)机制,从而能够显著提高I/O性能。

NIO的使用

import java.nio.*;
import java.nio.channels.*;
import java.io.*;
import java.nio.file.*;public class NIOExample {public static void main(String[] args) {Path inputPath = Paths.get("input.txt");Path outputPath = Paths.get("output.txt");try (FileChannel inputChannel = FileChannel.open(inputPath, StandardOpenOption.READ);FileChannel outputChannel = FileChannel.open(outputPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {ByteBuffer buffer = ByteBuffer.allocate(1024);while (inputChannel.read(buffer) != -1) {buffer.flip();outputChannel.write(buffer);buffer.clear();}} catch (IOException e) {e.printStackTrace();}}
}

在这个NIO示例中,我们使用FileChannelByteBuffer来实现文件的读写操作。与传统I/O不同,NIO使用FileChannel通过缓冲区读取数据,并且可以通过非阻塞的方式进行操作。数据通过ByteBufferflip()clear()方法进行管理。

传统I/O与NIO的性能对比

1. 阻塞与非阻塞模型

  • 传统I/O:每次I/O操作都是阻塞的,线程会等待操作完成后再继续执行。对于大量I/O请求,系统需要为每个请求分配线程,可能导致线程上下文切换和线程池资源消耗过大。
  • NIO:NIO通过非阻塞I/O模型允许线程在等待数据时进行其他任务处理,减少了线程的阻塞,提高了系统的吞吐量。

2. 内存管理与效率

  • 传统I/O:使用流时,数据是逐个字节地读取和写入。每次I/O操作都需要系统进行缓冲和内存分配,因此对于大量数据的读写,传统I/O的性能较差。
  • NIO:NIO使用ByteBuffer进行缓冲区管理,它能够一次性将大量数据加载到内存中,提高了数据的读写效率。并且,NIO的缓冲区可以直接操作内存中的数据,减少了内存复制的开销。

3. 文件处理性能对比

为了对比传统I/O与NIO的性能,下面是一个简单的文件复制性能测试代码,使用两种方式分别读取和写入一个100MB的文件。

传统I/O性能测试
public class TraditionalIOPerformanceTest {public static void main(String[] args) {long startTime = System.nanoTime();try (FileInputStream fis = new FileInputStream("input.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {fos.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}long endTime = System.nanoTime();System.out.println("Traditional IO Time: " + (endTime - startTime) / 1_000_000 + " ms");}
}
NIO性能测试
public class NIOPerformanceTest {public static void main(String[] args) {long startTime = System.nanoTime();Path inputPath = Paths.get("input.txt");Path outputPath = Paths.get("output.txt");try (FileChannel inputChannel = FileChannel.open(inputPath, StandardOpenOption.READ);FileChannel outputChannel = FileChannel.open(outputPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {ByteBuffer buffer = ByteBuffer.allocate(1024);while (inputChannel.read(buffer) != -1) {buffer.flip();outputChannel.write(buffer);buffer.clear();}} catch (IOException e) {e.printStackTrace();}long endTime = System.nanoTime();System.out.println("NIO Time: " + (endTime - startTime) / 1_000_000 + " ms");}
}

4. 结果分析

在文件复制性能测试中,通常情况下,NIO会比传统I/O快得多。原因在于:

  • 更少的内存复制:NIO直接操作缓冲区,避免了传统I/O中的多次内存复制。
  • 非阻塞I/O:NIO支持非阻塞I/O,允许线程在等待数据时继续执行其他任务,这对于并发环境中的性能提升尤为重要。
  • 高效的通道和缓冲区机制:NIO通道和缓冲区的设计优化了大数据量的处理,使得I/O操作更高效。

5. 适用场景对比

  • 传统I/O:适用于简单的、对性能要求不高的I/O操作,或者单线程、少量数据处理的场景。
  • NIO:适用于高并发、大数据量处理的场景,尤其是需要处理多个文件、网络连接的应用程序。NIO的非阻塞模型和选择器机制非常适合高效处理大量并发连接。

6. NIO与传统IO在网络编程中的应用

Java NIO提供了非常强大的工具来支持高效的网络编程。在传统I/O中,每当需要处理多个连接时,我们通常会为每个连接分配一个独立的线程,这会导致线程切换和上下文切换的开销,尤其在高并发的场景下,效率会显著下降。而NIO通过通道和选择器的机制,允许一个线程管理多个网络连接,从而大幅提高了并发处理能力。

传统I/O网络编程示例

在传统的阻塞I/O模型中,每个客户端连接都会创建一个独立的线程,线程会阻塞等待数据的读取和写入,这在处理大量并发连接时会遇到瓶颈。

import java.io.*;
import java.net.*;public class TraditionalIOServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(8080);while (true) {Socket clientSocket = serverSocket.accept();new Thread(new ClientHandler(clientSocket)).start();}}
}class ClientHandler implements Runnable {private Socket socket;public ClientHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) {String message;while ((message = reader.readLine()) != null) {writer.println("Echo: " + message);}} catch (IOException e) {e.printStackTrace();}}
}

在这个传统I/O的网络编程示例中,服务器每接收到一个客户端连接,就会为其创建一个新的线程。这种模型适用于低并发应用,但当连接数增加时,线程数量也会剧增,导致性能下降。

NIO网络编程示例

NIO通过SelectorChannel的组合,允许一个线程管理多个连接。以下是一个基于NIO的服务器示例,能够处理多个客户端连接,而不需要为每个连接创建独立线程。

import java.io.IOException;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;public class NIOServer {public static void main(String[] args) throws IOException {ServerSocketChannel serverChannel = ServerSocketChannel.open();serverChannel.bind(new InetSocketAddress(8080));serverChannel.configureBlocking(false);Selector selector = Selector.open();serverChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {if (selector.select() > 0) {for (SelectionKey key : selector.selectedKeys()) {if (key.isAcceptable()) {SocketChannel clientChannel = serverChannel.accept();clientChannel.configureBlocking(false);clientChannel.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel clientChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = clientChannel.read(buffer);if (bytesRead == -1) {clientChannel.close();} else {buffer.flip();clientChannel.write(buffer);}}selector.selectedKeys().remove(key);}}}}
}

在这个NIO示例中,服务器使用Selector来监听多个SocketChannel的事件,而不需要为每个连接创建独立的线程。当某个连接可读时,服务器通过read()方法处理数据并回写结果,而Selector机制使得一个线程能够同时处理多个连接。

这种非阻塞I/O和事件驱动模型使得NIO能够在高并发场景下表现出更好的性能,避免了线程的过多创建和上下文切换。

7. 高并发场景下的性能对比

NIO的优势

NIO的优势主要体现在以下几个方面:

  • 事件驱动模型:NIO通过Selector的事件驱动机制,让一个线程就能够管理多个连接,避免了大量线程的创建和销毁,提高了系统的可伸缩性。
  • 非阻塞I/O:在NIO中,I/O操作是非阻塞的,可以使线程在等待I/O完成时,继续处理其他任务。与传统I/O的阻塞式操作相比,非阻塞I/O能够显著减少线程阻塞的时间,尤其适用于需要频繁进行I/O操作的场景。
  • 内存管理:NIO通过ByteBuffer直接操作内存,避免了传统I/O中流的缓冲机制和内存复制的开销。通过一次性读写大量数据,NIO能提供更高效的内存利用率。

传统I/O的局限性

在高并发场景下,传统I/O的性能瓶颈主要体现在:

  • 线程消耗:每个连接需要分配一个线程,随着连接数的增加,线程的开销也会显著增加,导致系统资源的浪费。
  • 线程上下文切换:多个线程的上下文切换会造成CPU的额外负担,尤其是在高并发场景下,线程切换的开销可能会成为性能瓶颈。
  • 阻塞操作:传统I/O的每个操作都是阻塞的,线程在等待I/O时无法执行其他任务,降低了系统的并发处理能力。

为了进一步验证NIO在高并发场景下的优势,以下是一个简单的性能测试,模拟了一个同时处理1000个并发客户端连接的情境。

性能测试示例:传统I/O与NIO并发连接

public class IOPerformanceTest {private static final int CLIENT_COUNT = 1000;public static void main(String[] args) {long startTime = System.nanoTime();// 启动传统IO测试runTraditionalIOTest();long endTime = System.nanoTime();System.out.println("Traditional IO Time: " + (endTime - startTime) / 1_000_000 + " ms");startTime = System.nanoTime();// 启动NIO测试runNIOTest();endTime = System.nanoTime();System.out.println("NIO Time: " + (endTime - startTime) / 1_000_000 + " ms");}private static void runTraditionalIOTest() {// 模拟1000个客户端连接,每个客户端通过传统I/O进行通信for (int i = 0; i < CLIENT_COUNT; i++) {new Thread(() -> {try (Socket socket = new Socket("localhost", 8080);PrintWriter out = new PrintWriter(socket.getOutputStream(), true);BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {out.println("Hello Server");String response = in.readLine();} catch (IOException e) {e.printStackTrace();}}).start();}}private static void runNIOTest() {// 模拟1000个客户端连接,每个客户端通过NIO进行通信for (int i = 0; i < CLIENT_COUNT; i++) {new Thread(() -> {try (SocketChannel clientChannel = SocketChannel.open(new InetSocketAddress("localhost", 8080))) {ByteBuffer buffer = ByteBuffer.wrap("Hello Server".getBytes());clientChannel.write(buffer);buffer.clear();clientChannel.read(buffer);} catch (IOException e) {e.printStackTrace();}}).start();}}
}

在此示例中,我们模拟了1000个客户端通过传统I/O和NIO进行连接,并测量了每种方式所需的时间。通常情况下,NIO在处理大量并发连接时会明显优于传统I/O,尤其是在客户端数量上升时,NIO的性能优势更加明显。

8. NIO的优化与扩展

尽管NIO在高并发环境中具有明显的性能优势,但在某些情况下,NIO的编程模型可能较为复杂。为此,Java生态中也提供了许多基于NIO的高级库和框架,这些工具封装了底层复杂性,使得开发者能够更容易地使用NIO进行高效的网络编程。

  • Netty:一个基于NIO的高性能网络通信框架,广泛应用于分布式系统和高并发应用中。Netty通过优化I/O处理机制,提供了比Java NIO更高效、更易用的解决方案。
  • AIO(Asynchronous I/O):Java 7引入的异步I/O(AIO)通过进一步简化I/O操作的编程模型,进一步提高了高并发场景下的性能和可扩展性。

通过使用这些库和框架,开发者可以更加专注于业务逻辑而不必深入到底层的I/O细节,同时还能充分发挥NIO和AIO的优势。

结语

NIO通过引入非阻塞I/O、通道和选择器等机制,极大提高

了Java在高并发场景下的性能,特别是在网络编程和大规模数据处理方面。与传统I/O相比,NIO能够在不增加大量线程的情况下,处理更多并发请求,减少资源消耗并提高响应效率。在高并发系统中,采用NIO不仅能够提高吞吐量,还能够显著提升系统的可伸缩性。

在这里插入图片描述

相关文章:

Java NIO与传统IO性能对比分析

Java NIO与传统IO性能对比分析 在Java中&#xff0c;I/O&#xff08;输入输出&#xff09;操作是开发中最常见的任务之一。传统的I/O方式基于阻塞模型&#xff0c;而Java NIO&#xff08;New I/O&#xff09;引入了非阻塞和基于通道&#xff08;Channel&#xff09;和缓冲区&a…...

14.7 LangChain Experimental 模块解析:解锁 Auto-GPT 开发新范式

LangChain Experimental 模块解析:解锁 Auto-GPT 开发新范式 关键词:LangChain Experimental、Auto-GPT 实现、自主智能体开发、Agent 架构设计、实验性功能实践 1. LangChain Experimental 模块的定位与核心能力 模块定位解析: #mermaid-svg-4xz2OlZBUFjkBmqw {font-fami…...

wps中的js开发

严格区分大小写 /*** learn_js Macro*/ function test() {Range(D7).Value2Selection.Value2; // Selection.formula "100" }function Workbook_SheetSelectionChange(Sh, Target) {if(Sh.Name Sheet1) {test();}}function test2() {// 把I4单元格及其周边有数的单…...

day16_推荐系统和总结

文章目录 day16_推荐系统和总结一、推荐实现1、基于流行度推荐&#xff08;掌握&#xff09;1.1 近期热门商品推荐1.2 个人热门商品推荐 2、基于隐语义模型的协同过滤推荐&#xff08;了解&#xff09;2.1 ALS算法介绍2.2 推荐代码 3、基于物品的协同过滤推荐&#xff08;了解&…...

一文说清楚编码、摘要、加密、公钥、私钥、解密、签名、验签

编码 对信息进行编码&#xff0c;没有信息损失&#xff0c;任何人都能通过编码方式对信息进行解码。例如 ASCII 码&#xff0c;base64 编码。 例如下面是 ASCII 编码表&#xff1a; ​ 摘要 对信息计算摘要值&#xff0c;有信息损失&#xff0c;例如 md5 摘要&#xff0c;sh…...

Repeated Sequence

记suma[1]a[2]a[3]...a[n]。 该序列以a[1]&#xff0c;a[2]&#xff0c;a[3]....a[n]为循环节&#xff0c;明显的&#xff0c;问题可转化为:s%sum是否为该序列的某个连续子序列和。 断环为链。将a复制一份。 枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O&#x…...

CT dicom 去除床板 去除床位,检查床去除

1. 前言 医院拍摄患者CT与MRI 图像&#xff0c; 但是CT图像中就会出现检查床的区域&#xff0c;来看CT扫描设备是什么样子的&#xff0c;红色标出区域 可以在图中看到&#xff0c;在头部位置安装有固定头部的类似支架的东西&#xff0c;这个东西拍摄出来时什么样子呢&#xff…...

react 踩坑记 too many re-renders.

报错信息&#xff1a; too many re-renders. React limits the number of randers to prevent an infinite loop. 需求 tabs只有特定标签页才展示某些按钮 button要用 传递函数引用方式 ()>{} *还有要注意子组件内loading触发 导致的重复渲染...

YOLOv8与BiFormer注意力机制的融合:提升多场景目标检测性能的研究

文章目录 1. YOLOv8的改进背景2. BiFormer注意力机制的核心原理2.1 Bi-level Attention结构2.2 路由策略与加权融合 3. YOLOv8与BiFormer的结合3.1 YOLOv8架构概述3.2 BiFormer与YOLOv8的融合策略 4. 实现代码示例5. 结果分析与实验5.1 数据集与实验设置5.2 实验结果 6. 进一步…...

Ubuntu24.04LTS的下载安装超细图文教程(VMware虚拟机及正常安装)

&#x1f638;个人主页&#x1f449;&#xff1a;神兽汤姆猫 &#x1f4d6;系列专栏&#xff1a;开发语言环境配置 、 Java学习 、Java面试 、Markdown等 学习上的每一次进步&#xff0c;均来自于平时的努力与坚持。 &#x1f495;如果此篇文章对您有帮助的话&#xff0c;请点…...

c++贪心系列

各位小伙伴们新年好呀&#xff0c;这是年后的第一篇文章&#xff0c;那么还是一样&#xff0c;我们继续学习这个贪心算法。 第一题 题目链接 2418. 按身高排序 - 力扣&#xff08;LeetCode&#xff09; 题目解析 代码原理 方法一 1.先创建一个下标数组&#xff0c;将两个数…...

爬虫第七篇数据爬取及解析

这篇博客旨在分享学习过程中的心得和体会&#xff0c;如果有错误请指出&#xff0c;感谢大家。 经过前面的学习&#xff0c;那么我们也就进入了数据爬取的阶段&#xff0c;大家跟着我的步伐一起来学习一下&#xff0c;爬虫的数据爬取与数据解析&#xff08;本篇主要针对于带有…...

LangChain 技术入门指南:探索语言模型的无限可能

在当今的技术领域&#xff0c;LangChain 正逐渐崭露头角&#xff0c;成为开发语言模型应用的强大工具。如果你渴望深入了解并掌握这一技术&#xff0c;那么就跟随本文一起开启 LangChain 的入门之旅吧&#xff01; (后续将持续输出关于LangChain的技术文章,有兴趣的同学可以关注…...

解锁D3.js与PlantUML的交互奥秘:探索知识图谱数据可视化新领域

解锁D3.js与PlantUML的交互魔法&#xff1a;数据可视化新征程 在前端开发的广袤天地里&#xff0c;数据可视化一直是一颗璀璨的明珠&#xff0c;吸引着无数开发者探索其奥秘。而当D3.js这一强大的JavaScript库&#xff0c;遇上专注于创建UML图的PlantUML&#xff0c;一场奇妙的…...

OpenCV机器学习(8)随机森林(Random Forests)算法cv::ml::RTrees类

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::ml::RTrees 是 OpenCV 机器学习模块中的一部分&#xff0c;用于实现随机森林&#xff08;Random Forests&#xff09;算法。随机森林是一种集…...

Java四大框架深度剖析:MyBatis、Spring、SpringMVC与SpringBoot

目录 前言&#xff1a; 一、MyBatis框架 1. 概述 2. 核心特性 3. 应用场景 4. 示例代码 二、Spring框架 1. 概述 2. 核心模块 3. 应用场景 4. 示例代码 三、SpringMVC框架 1. 概述 2. 核心特性 3. 应用场景 4. 示例代码 四、SpringBoot框架 1. 概述 2. 核心…...

MySQL系列之身份鉴别(安全)

导览 前言Q&#xff1a;如何保障MySQL数据库身份鉴别的有效性一、有效性检查 1. 用户唯一2. 启用密码验证3. 是否存在空口令用户4. 是否启用口令复杂度校验5. 是否设置口令的有效期6. 是否限制登录失败尝试次数7. 是否设置&#xff08;超过尝试次数&#xff09;锁定的最小时长…...

纯手工搭建整套CI/CD流水线指南

目录 一、前言 二、环境准备 1、服务器开荒&#xff08;192.168.1.200&#xff09; 2、离线资源清单&#xff08;提前用U盘拷好&#xff09; 三、硬核安装&#xff1a;比拧螺丝还细的步骤 Step1&#xff1a;搭建GitLab&#xff08;注意&#xff01;这是只内存饕餮&#xf…...

侯捷 C++ 课程学习笔记:C++ 基础与演化

一、课程基础要求 在侯捷老师C 课程中&#xff0c;首先强调了学习 C 前应具备的基础知识。这些基础知识对于理解 C 的核心概念和编程技巧至关重要。 掌握某种过程式语言&#xff08;C 语言最佳&#xff09;&#xff1a; 变量&#xff08;Variables&#xff09;&#xff1a;理解…...

LangChain:AI大模型开发与分布式系统设计

文章目录 第一部分&#xff1a;大模型与 LangChain 基础1.1 大语言模型概述1.2 LangChain 基础 第二部分&#xff1a;模型初始化与调用2.1 自定义大模型架构 第三部分&#xff1a;高级模型设计与优化3.1 提示工程与模型调优3.2 高效处理大规模数据 第四部分&#xff1a;分布式系…...

【第5章 AI Agent 与工具调用】5.7 章节实战(二):多Agent协作的信息抽取系统

写在前面 在真实业务场景中,信息抽取往往不是单一模型能够“一键完成”的任务。面对海量、多源、跨领域的文本数据,单体的抽取模型往往面临 **性能瓶颈**、**可维护性差**、**扩展困难** 等问题。于是,**多 Agent 协作**(Multi‑Agent Collaboration) 成为了一种被广泛讨…...

终极指南:如何让老Mac重获新生,体验最新macOS系统

终极指南&#xff1a;如何让老Mac重获新生&#xff0c;体验最新macOS系统 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否有一台被苹果"抛弃"…...

【后端开发】(真实场景/面试题) 从 1 亿用户表聊起:手机号字段到底该用 varchar、char 还是 bigint?

文章目录前言1 手机号到底是不是“数字”&#xff1f;1.1 为什么不能直接用 int&#xff1f;1.2 bigint 能存&#xff0c;为什么也不推荐&#xff1f;1.3 手机号更像身份证号&#xff0c;而不是年龄2 在 1 亿用户表下&#xff0c;字段类型怎么选&#xff1f;2.1 varchar(11) 够…...

Snap.Hutao原神工具箱:解决玩家痛点的专业桌面助手

Snap.Hutao原神工具箱&#xff1a;解决玩家痛点的专业桌面助手 【免费下载链接】Snap.Hutao 实用的开源多功能原神工具箱 &#x1f9f0; / Multifunctional Open-Source Genshin Impact Toolkit &#x1f9f0; 项目地址: https://gitcode.com/GitHub_Trending/sn/Snap.Hutao …...

Tool.Net 3.0.0正式版发布:如何用MapApiRoute和AshxRoute特性玩转灵活API路由?

Tool.Net 3.0.0路由革命&#xff1a;MapApiRoute与AshxRoute的实战进阶指南 当ASP.NET Core开发者遇到需要为复杂业务系统设计多层级API路由时&#xff0c;传统配置方式往往显得力不从心。Tool.Net 3.0.0带来的MapApiRoute方法与AshxRoute特性组合&#xff0c;正在改变这一局面…...

3步永久备份微信聊天记录:WeChatExporter让你的珍贵对话不再丢失

3步永久备份微信聊天记录&#xff1a;WeChatExporter让你的珍贵对话不再丢失 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾担心手机丢失或更换设备后&#xff…...

HEIF Utility:Windows平台HEIF图片查看与转换的终极解决方案

HEIF Utility&#xff1a;Windows平台HEIF图片查看与转换的终极解决方案 【免费下载链接】HEIF-Utility HEIF Utility - View/Convert Apple HEIF images on Windows. 项目地址: https://gitcode.com/gh_mirrors/he/HEIF-Utility 随着iPhone等苹果设备全面采用HEIF格式作…...

3个关键场景解密CentOS-WSL:为什么开发者需要这个Windows上的Linux神器

3个关键场景解密CentOS-WSL&#xff1a;为什么开发者需要这个Windows上的Linux神器 【免费下载链接】CentOS-WSL A GitHub Actions automated CentOS RootFS to use with WSL 项目地址: https://gitcode.com/gh_mirrors/ce/CentOS-WSL 在Windows系统上无缝运行企业级Cen…...

Space Thumbnails:彻底解决Windows资源管理器3D模型预览难题的终极方案

Space Thumbnails&#xff1a;彻底解决Windows资源管理器3D模型预览难题的终极方案 【免费下载链接】space-thumbnails Generates preview thumbnails for 3D model files. Provide a Windows Explorer extensions that adds preview thumbnails for 3D model files. 项目地址…...

基于LLM的聊天机器人开发框架:架构设计与工程实践

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫zhaoyingjun/chatbot。乍一看名字&#xff0c;你可能会觉得这又是一个基于某个大语言模型API的简单封装&#xff0c;或者是一个玩具级别的对话应用。但当我真正点进去&#xff0c;把代码拉下来跑了一遍…...