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

JDK 中 NIO 框架设计与实现:深入剖析及实战样例

一、引言

在 Java 的发展历程中,I/O(Input/Output)操作一直是构建高效、稳定应用程序的关键环节。传统的 Java I/O 操作基于流(Stream)的方式,虽然简单易用,但在面对高并发、大规模数据传输等场景时,性能瓶颈逐渐凸显。为了满足日益增长的应用需求,Java NIO(New I/O)应运而生。NIO 框架提供了一套全新的 I/O 操作方式,通过引入缓冲区(Buffer)、通道(Channel)和选择器(Selector)等核心概念,极大地提升了 I/O 操作的效率和灵活性,为构建高性能的网络应用、文件处理系统等提供了有力支持。本文将深入探讨 JDK 中 NIO 框架的设计与实现,从背景历史、功能点、业务场景、底层原理等多个维度进行详细剖析,并通过实际的 Java 样例帮助读者更好地理解和掌握 NIO 框架的使用方法。

二、NIO 框架的背景历史

2.1 传统 I/O 的局限性

在 NIO 出现之前,Java 的 I/O 操作主要基于流的方式。传统的流 I/O 是一种阻塞式 I/O 模型,即当一个线程调用 read () 或 write () 方法时,该线程会被阻塞,直到有数据可读或数据被完全写入。这种阻塞式的操作方式在处理单线程或少量并发请求时表现良好,但在高并发场景下,会导致大量线程被阻塞,从而占用大量系统资源,严重影响系统的性能和可扩展性。例如,在一个基于传统 I/O 的网络服务器中,每处理一个客户端连接都需要创建一个新的线程,当客户端连接数量增加时,线程数量也会随之急剧增加,这会导致系统的内存开销增大,线程上下文切换频繁,最终导致系统性能下降甚至崩溃。

2.2 NIO 的诞生与发展

为了解决传统 I/O 的局限性,Java 1.4 版本引入了 NIO 框架。NIO 框架采用了非阻塞式 I/O 模型,通过使用缓冲区和通道来实现数据的读写操作,同时引入了选择器机制,使得一个线程可以同时处理多个通道的 I/O 事件,大大提高了系统的并发处理能力。随着 Java 的不断发展,NIO 框架也在持续演进和完善。Java 7 中引入了 NIO.2(也称为 AIO,即 Asynchronous I/O),进一步扩展了 NIO 的功能,提供了异步 I/O 操作,使得应用程序可以在 I/O 操作完成后得到通知,而无需一直等待,从而进一步提升了系统的性能和响应速度。

三、NIO 框架的功能点

3.1 缓冲区(Buffer)

缓冲区是 NIO 中用于存储数据的容器,它本质上是一个数组,可以存储各种基本数据类型的数据。与传统的流 I/O 不同,NIO 的读写操作都是通过缓冲区来进行的。缓冲区具有以下几个重要的属性:

  • 容量(Capacity):缓冲区能够容纳的数据元素的最大数量,一旦缓冲区被创建,其容量就不能被改变。
  • 位置(Position):下一个要被读或写的数据元素的索引,初始值为 0,随着读写操作的进行,位置会自动更新。
  • 界限(Limit):缓冲区中可以操作的数据的最后一个元素的索引,位置的值不能超过界限。
  • 标记(Mark):用于临时保存位置的值,方便后续恢复到该位置。

Java 提供了多种类型的缓冲区,如 ByteBuffer、CharBuffer、IntBuffer 等,以满足不同类型数据的存储需求。例如,ByteBuffer 是最常用的缓冲区类型,可以用于存储字节数据,常用于网络通信和文件读写操作。

3.2 通道(Channel)

通道是 NIO 中用于进行 I/O 操作的实体,它类似于传统 I/O 中的流,但与流不同的是,通道是双向的,可以同时进行读写操作,并且通道支持非阻塞式 I/O 操作。通道不能直接读写数据,必须通过缓冲区来进行数据的传输。Java 提供了多种类型的通道,如 FileChannel 用于文件的读写操作,SocketChannel 和 ServerSocketChannel 用于网络通信等。

3.3 选择器(Selector)

选择器是 NIO 框架中实现非阻塞式 I/O 多路复用的关键组件。通过选择器,一个线程可以同时监控多个通道的 I/O 事件,如可读、可写、连接建立等。当某个通道有 I/O 事件发生时,选择器会通知应用程序,应用程序可以根据事件类型对相应的通道进行处理。这样,一个线程就可以高效地处理多个通道的 I/O 操作,大大提高了系统的并发处理能力。选择器的使用步骤如下:

  1. 创建选择器:通过Selector.open()方法创建一个选择器实例。
  2. 将通道注册到选择器上:通道必须设置为非阻塞模式,然后通过channel.register(selector, selectionKey)方法将通道注册到选择器上,并指定要监听的事件类型(如SelectionKey.OP_READ表示监听读事件)。
  3. 轮询选择器:通过selector.select()方法阻塞等待,直到有注册的通道发生感兴趣的事件。
  4. 处理事件:通过selector.selectedKeys()方法获取发生事件的通道的选择键集合,然后遍历集合,根据选择键的事件类型对相应的通道进行处理。

四、NIO 框架的业务场景

4.1 高性能网络服务器

在构建高性能的网络服务器时,NIO 框架的非阻塞式 I/O 和多路复用机制可以大大提高服务器的并发处理能力。通过使用选择器,一个线程可以同时处理多个客户端连接的 I/O 操作,避免了大量线程的创建和切换,从而降低了系统资源消耗,提高了服务器的性能和稳定性。例如,在构建一个基于 HTTP 协议的 Web 服务器时,可以使用 NIO 框架来处理大量的客户端请求,实现高效的并发处理。

4.2 文件处理系统

在文件处理系统中,NIO 的通道和缓冲区机制可以提高文件读写的效率。通过使用 FileChannel,可以实现文件的异步读写操作,减少线程的阻塞时间,提高系统的整体性能。例如,在进行大规模文件的上传和下载时,使用 NIO 框架可以显著提升文件传输的速度和效率。

4.3 实时通信系统

在实时通信系统中,如即时通讯、在线游戏等,需要能够及时处理大量的客户端连接和消息传输。NIO 框架的非阻塞式 I/O 和多路复用机制可以满足实时通信系统对高并发和低延迟的要求,确保系统能够快速响应客户端的请求,实现高效的实时通信。

五、NIO 框架的底层原理

5.1 非阻塞式 I/O 模型

NIO 框架采用了非阻塞式 I/O 模型,这是其实现高性能 I/O 操作的核心原理之一。在非阻塞式 I/O 模型中,当线程调用通道的 read () 或 write () 方法时,如果没有数据可读或可写,线程不会被阻塞,而是立即返回一个状态值,应用程序可以根据这个状态值来决定下一步的操作。例如,当调用 read () 方法时,如果没有数据可读,read () 方法会返回 0 或 - 1,应用程序可以继续执行其他任务,而不是等待数据的到来。这种非阻塞式的操作方式使得线程可以在等待 I/O 操作完成的同时执行其他任务,大大提高了线程的利用率。

5.2 多路复用机制

多路复用机制是 NIO 框架实现高效并发处理的另一个关键原理。通过选择器,一个线程可以同时监控多个通道的 I/O 事件。选择器会不断地轮询注册到它上面的通道,当某个通道有 I/O 事件发生时,选择器会将该通道的选择键加入到已选择键集合中。应用程序可以通过遍历已选择键集合,获取发生事件的通道,并对其进行相应的处理。这种多路复用机制避免了大量线程的创建和切换,减少了系统资源的消耗,提高了系统的并发处理能力。

5.3 缓冲区的内存管理

NIO 框架中的缓冲区采用了一种特殊的内存管理方式,以提高数据读写的效率。缓冲区可以分为堆内缓冲区和堆外缓冲区。堆内缓冲区是在 Java 堆内存中分配的,它的创建和销毁由 Java 垃圾回收器管理,使用方便,但在进行 I/O 操作时,需要将数据从堆内存复制到内核空间,增加了数据传输的开销。堆外缓冲区是在 Java 堆内存之外分配的,它直接与操作系统的物理内存进行交互,避免了数据在堆内存和内核空间之间的复制,从而提高了 I/O 操作的效率。但是,堆外缓冲区的创建和销毁需要手动管理,使用不当可能会导致内存泄漏等问题。

六、NIO 框架的 Java 样例

6.1 文件读写样例

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class FileIOExample {public static void main(String[] args) {String sourceFilePath = "source.txt";String targetFilePath = "target.txt";try (FileInputStream fis = new FileInputStream(sourceFilePath);FileOutputStream fos = new FileOutputStream(targetFilePath);FileChannel sourceChannel = fis.getChannel();FileChannel targetChannel = fos.getChannel()) {ByteBuffer buffer = ByteBuffer.allocate(1024);while (sourceChannel.read(buffer)!= -1) {buffer.flip();targetChannel.write(buffer);buffer.clear();}System.out.println("文件复制完成。");} catch (IOException e) {e.printStackTrace();}}
}

在这个样例中,我们使用 FileChannel 和 ByteBuffer 实现了文件的复制操作。首先创建了 FileInputStream 和 FileOutputStream,然后通过它们获取对应的 FileChannel。接着创建了一个 ByteBuffer,用于存储从源文件读取的数据。通过循环读取源文件的数据到缓冲区,然后将缓冲区的数据写入目标文件,完成文件的复制。

6.2 网络通信样例(客户端)

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class NioClientExample {public static void main(String[] args) {String serverIp = "127.0.0.1";int serverPort = 8888;try (SocketChannel socketChannel = SocketChannel.open()) {socketChannel.connect(new InetSocketAddress(serverIp, serverPort));String message = "Hello, server!";ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());socketChannel.write(buffer);buffer.clear();int bytesRead = socketChannel.read(buffer);if (bytesRead > 0) {buffer.flip();byte[] response = new byte[bytesRead];buffer.get(response);System.out.println("收到服务器响应: " + new String(response));}} catch (IOException e) {e.printStackTrace();}}
}

6.2 网络通信样例(服务器端)

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class NioServerExample {public static void main(String[] args) {int port = 8888;try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {serverSocketChannel.bind(new InetSocketAddress(port));serverSocketChannel.configureBlocking(false);System.out.println("服务器启动,等待客户端连接...");while (true) {SocketChannel socketChannel = serverSocketChannel.accept();if (socketChannel!= null) {socketChannel.configureBlocking(false);System.out.println("客户端连接成功: " + socketChannel.getRemoteAddress());ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = socketChannel.read(buffer);if (bytesRead > 0) {buffer.flip();byte[] request = new byte[bytesRead];buffer.get(request);System.out.println("收到客户端请求: " + new String(request));String response = "Hello, client!";buffer = ByteBuffer.wrap(response.getBytes());socketChannel.write(buffer);}}}} catch (IOException e) {e.printStackTrace();}}
}

在这两个样例中,我们实现了一个简单的基于 NIO 的网络通信程序。客户端通过 SocketChannel 连接到服务器,并发送一条消息,然后接收服务器的响应。服务器通过 ServerSocketChannel 监听客户端的连接请求,当有客户端连接时,接收客户端发送的消息,并返回一条响应消息。

6.3 使用选择器的网络通信样例(服务器端)

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class NioSelectorServerExample {public static void main(String[] args) {int port = 8888;try (Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {serverSocketChannel.bind(new InetSocketAddress(port));serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务器启动,等待客户端连接...");while (true) {int readyChannels = selector.select();if (readyChannels == 0) {continue;}Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel socketChannel = ssc.accept();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("客户端连接成功: " + socketChannel.getRemoteAddress());} else if (key.isReadable()) {SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = socketChannel.read(buffer);if (bytesRead > 0) {buffer.flip();byte[] request = new byte[bytesRead];buffer.get(request);System.out.println("收到客户端请求: " + new String(request));String response = "Hello, client!";buffer = ByteBuffer.wrap(response.getBytes());socketChannel.write(buffer);}}keyIterator.remove();}}} catch (IOException e) {e.printStackTrace();}}
}

在这个样例中,我们使用了选择器来实现一个高效的网络服务器。服务器通过选择器监听多个客户端连接的 I/O 事件,当有客户端连接请求或数据可读事件发生时,选择器会通知应用程序,应用程序根据事件类型对相应的通道进行处理。这样,一个线程就可以同时处理多个客户端连接的 I/O 操作,大大提高了服务器的并发处理能力。

七、总结

NIO 框架作为 Java I/O 体系中的重要组成部分,为开发高性能、高并发的应用程序提供了强大的支持。通过引入缓冲区、通道和选择器等核心概念,NIO 框架实现了非阻塞式 I/O 操作和多路复用机制,有效地解决了传统 I/O 在高并发场景下的性能瓶颈问题。本文从 NIO 框架的背景历史、功能点、业务场景、底层原理等多个方面进行了详细的介绍,并通过实际的 Java 样例展示了 NIO 框架的使用方法。希望读者通过本文的学习,能够深入理解 NIO 框架的设计与实现,掌握 NIO 框架的使用技巧,从而在实际项目中更好地应用 NIO 框架,提升应用程序的性能和可扩展性。随着技术的不断发展,NIO 框架也在持续演进和完善,未来将会为开发者提供更多更强大的功能和特性。

相关文章:

JDK 中 NIO 框架设计与实现:深入剖析及实战样例

一、引言 在 Java 的发展历程中&#xff0c;I/O&#xff08;Input/Output&#xff09;操作一直是构建高效、稳定应用程序的关键环节。传统的 Java I/O 操作基于流&#xff08;Stream&#xff09;的方式&#xff0c;虽然简单易用&#xff0c;但在面对高并发、大规模数据传输等场…...

基于springboot校园点歌系统

基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台&#xff0c;它能够丰富学生的校园生活&#xff0c;提升学生的娱乐体验。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 在校园环境中&#xff0c;学生们对于音乐有着浓厚的兴趣&#xff0c;传…...

Spring 核心技术解析【纯干货版】- IX:Spring 数据访问模块 Spring-Jdbc 模块精讲

在现代企业级应用中&#xff0c;数据访问层的稳定性和高效性至关重要。为了简化和优化数据库操作&#xff0c;Spring Framework 提供了 Spring-JDBC 模块&#xff0c;旨在通过高度封装的 JDBC 操作&#xff0c;简化开发者的编码负担&#xff0c;减少冗余代码&#xff0c;同时提…...

React开发中箭头函数返回值陷阱的深度解析

React开发中箭头函数返回值陷阱的深度解析 一、箭头函数的隐式返回机制&#xff1a;简洁背后的规则二、块函数体中的显式返回要求&#xff1a;容易被忽视的细节三、真实场景下的案例分析案例1&#xff1a;忘记return导致组件渲染失败案例2&#xff1a;异步操作中的返回值陷阱 四…...

线程同步时定义 std::mutex 为什么要在前面添加 mutable 关键字

在C中&#xff0c;mutable关键字用于修饰类的成员变量&#xff0c;表示即使在一个const对象中&#xff0c;该成员变量也可以被修改。对于mutex这样的同步原语&#xff0c;使用mutable是必要的&#xff0c;原因如下&#xff1a; 1. 为什么需要 mutable&#xff1f; mutex通常用…...

【多线程】线程池核心数到底如何配置?

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 前置回顾2. 动态线程池2.1 JMX 的介绍2.1.1 MBeans 介绍 2.2 使用 JMX jconsole 实现动态修改线程池2.2.…...

Linux find 命令 | grep 命令 | 查找 / 列出文件或目录路径 | 示例

注&#xff1a;本文为 “Linux find 命令 | grep 命令使用” 相关文章合辑。 未整理去重。 如何在 Linux 中查找文件 作者&#xff1a; Lewis Cowles 译者&#xff1a; LCTT geekpi | 2018-04-28 07:09 使用简单的命令在 Linux 下基于类型、内容等快速查找文件。 如果你是 W…...

爬楼梯(dp)杭电复试

一个楼梯共有 nn 级台阶&#xff0c;每次可以走一级或者两级或者三级&#xff0c;问从第 00 级台阶走到第 nn 级台阶一共有多少种方案。 输入格式 一个整数 NN。 输出格式 一个整数&#xff0c;表示方案总数。 数据范围 1≤N≤201≤N≤20 输入样例&#xff1a; 4输出样…...

JVM执行引擎

一、执行引擎的概述: 执行引擎是]ava虚拟机核心的组成部分之一; “虚拟机”是一个相对于“物理机”的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行引擎则…...

企业四要素如何用PHP进行调用

一、什么是企业四要素&#xff1f; 企业四要素接口是在企业三要素&#xff08;企业名称、统一社会信用代码、法定代表人姓名&#xff09;的基础上&#xff0c;增加了一个关键要素&#xff0c;通常是企业注册号或企业银行账户信息。这种接口主要用于更全面的企业信息验证&#x…...

基于springboot河南省旅游管理系统

基于Spring Boot的河南省旅游管理系统是一种专为河南省旅游行业设计的信息管理系统&#xff0c;旨在整合和管理河南省的旅游资源信息&#xff0c;为游客提供准确、全面的旅游攻略和服务。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 河南省作为中国的中部省份&…...

arm 下 多线程访问同一变量 ,使用原子操作 性能差问题

arm下原子操作性能差的原因 Linux Kernel(armv8-aarch64) 的原子操作的底层实现 - 极术社区 - 连接开发者与智能计算生态 arm 下如何解决 ARMs LSE (for atomics) and MySQL – MySQL On ARM – All you need to know about MySQL (and its variants) on ARM. arm 下lse 和…...

嵌入式工程师必学(143):模拟信号链基础

概述: 我们每天使用的许多电子设备,以及我们赖以生存的电子设备,如果不使用电子工程师设计的实际输入信号,就无法运行。 模拟信号链由四个主要元件组成:传感器、放大器、滤波器和模数转换器 (ADC)。这些传感器用于检测、调节模拟信号并将其转换为适合由微控制器或其他数…...

PyQt6/PySide6 的 QDialog 类

QDialog 是 PyQt6 或 PySide6 库中用于创建对话框的类。对话框是一种特殊的窗口&#xff0c;通常用于与用户进行短期交互&#xff0c;如输入信息、显示消息或选择选项等。QDialog 提供了丰富的功能和灵活性&#xff0c;使得开发者可以轻松地创建各种类型的对话框。下面我将详细…...

【AI日记】25.02.05 自由不是一种工具

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛&#xff1a;Backpack Prediction Challenge感想&#xff1a;这次比赛的数据集的一大特点是信号过弱或者噪声过大&#xff0c;也是一大难点&#xff0c;即使kaggle 官方增加了一…...

【原子工具】快速幂 快速乘

题幂算.一切即1 阴阳迭变积微著&#xff0c;叠浪层峦瞬息功 莫道浮生千万事&#xff0c;元知万象一归宗 文章目录 快速幂原始快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 模下意义的快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 快速乘龟速…...

2024年12月 Scratch 图形化(四级)真题解析 中国电子学会全国青少年软件编程等级考试

202412 Scratch 图形化&#xff08;四级&#xff09;真题解析 中国电子学会全国青少年软件编程等级考试 一、选择题(共10题&#xff0c;共30分) 第 1 题 列表存放全班同学的身高&#xff0c;小猫运行下列程序&#xff0c;下列选项说法正确的是&#xff1f;&#xff08; &#…...

【面试宝典】机器学习:深度解析高频面试题与解答策略

目录 &#x1f354; 机器学习中特征的理解 &#x1f354; 机器学习三要素如何理解? &#x1f354; 机器学习中&#xff0c;有哪些特征选择的⼯程⽅法&#xff1f; &#x1f354; 机器学习中的正负样本 &#x1f354; 线性分类器与⾮线性分类器的区别及优劣 &#x1f354…...

使用 ElementUI 和 Spring 实现稳定可靠的文件上传和下载功能

前端(ElementUI) 1. 文件上传 使用 el-upload 组件配置上传接口处理上传成功和失败<template><div><el-uploadclass="upload-demo"action="http://your-server-url/upload":on-success="handleSuccess":on-error="handle…...

Linux驱动---字符设备

目录 一、基础简介 1.1、Linux设备驱动分类 1.2、字符设备驱动概念 二、驱动基本构成 2.1、驱动模块的加载和卸载 2.2、添加LICENNSE以及其他信息 三、字符设备驱动开发步骤 3.1、分配主次设备号 3.1.1 主次设备号 3.1.2静态注册设备号 3.1.3动态注册设备号 3.1.4释…...

FastReport.NET控件篇之交叉表控件

认识交叉表 上面是交叉表的原型&#xff0c;关键的三个单元格。 单元格①&#xff1a;用于扩展行数据&#xff0c;譬如打印学生成绩表时&#xff0c;每个学生一行&#xff0c;那么这个地方就是以学生姓名列进行打印。 单元格②&#xff1a;用于扩展列数据&#xff0c;譬如打印…...

构建高效复杂系统的关键:架构与模块详解

目录 一、复杂系统组成 二、接入系统 (Access System) 三、应用系统 (Application System) 四、基础平台 (Foundation Platform) 五、中间件 (Abundant External Middleware) 六、支撑系统 (Supporting System) 七、总结 参考文章 干货分享&#xff0c;感谢您的阅读&am…...

C++之递归

递归 递归函数是指一个函数直接或间接地调用自身。递归函数通常用于解决可以分解为相似子问题的问题&#xff0c;例如计算阶乘、斐波那契数列、遍历树结构等 基本结构 一个递归函数通常包含两个部分&#xff1a; 基准条件&#xff08;Base Case&#xff09;&#xff1a;这是…...

pushgateway指标聚合问题

一 问题现象 一个job有多个实例推送指标&#xff0c;但是从pushgateway上看这个job的instance字段&#xff0c;只显示一个实例的ip&#xff0c;而不是多个实例。导致在grafana上无法正常根据ip查看监控。 应用的prometheus的配置 management:metrics:tags:application: ${spr…...

mini-lsm通关笔记Week2Day7

项目地址&#xff1a;https://github.com/skyzh/mini-lsm 个人实现地址&#xff1a;https://gitee.com/cnyuyang/mini-lsm 在上一章中&#xff0c;您已经构建了一个完整的基于LSM的存储引擎。在本周末&#xff0c;我们将实现存储引擎的一些简单但重要的优化。欢迎来到Mini-LSM的…...

[权限提升] Windows 提权 维持 — 系统错误配置提权 - 注册表权限配置错误提权

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;注册表权限配置错误提权原理 通常 Windows 中的服务都是以 System 权限运行的&#xff0c;而 Windows 的服务程序的启动路径又是存放在注册表中的&#xff0c;若注册表配置不…...

产品经理的人工智能课 02 - 自然语言处理

产品经理的人工智能课 02 - 自然语言处理 1 自然语言处理是什么2 一个 NLP 算法的例子——n-gram 模型3 预处理与重要概念3.1 分词 Token3.2 词向量化表示与 Word2Vec 4 与大语言模型的交互过程参考链接 大语言模型&#xff08;Large Language Models, LLMs&#xff09;是自然语…...

软件工程导论三级项目报告--《软件工程》课程网站

《软件工程》课程网站 摘要 本文详细介绍了《软件工程》课程网站的设计与实现方案&#xff0c;包括可行性分析、需求分析、总体设计、详细设计、测试用例。首先&#xff0c;通过可行性分析从各方面确认了该工程的可实现性&#xff0c;接着需求分析明确了系统的目标用户群和功能…...

FPGA|IP核PLL调用测试:调用IP核

1、选择tools-》Megawizard plug-In manager 2、选择第一项&#xff0c;下一步 3、选择ATPLL&#xff0c;芯片系列、和输出文件类型&#xff0c;输出文件名称&#xff0c;单击next 4、出现配置PLL界面 5、选择输入时钟频率&#xff0c;单击next 6、生成reset、和locked信号&…...

leetcode_双指针 160.相交链表

160.相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 思路: 本题中&#xff0c;交点不是数值相等&#xff0c;而是指针相等 双指针遍历两遍后必定相遇&#xff0c…...

TongSearch3.0.4.0安装和使用指引(by lqw)

文章目录 安装准备手册说明支持的数据类型安装控制台安装单节点(如需集群请跳过这一节)解压和启动开启X-Pack Security和生成p12证书&#xff08;之后配置内置密码和ssl要用到&#xff09;配置内置用户密码配置ssl&#xff08;先配置内置用户密码再配ssl&#xff09;配置控制台…...

2021.3.1的android studio版本就很好用

使用最新版的studio有个问题就是gradle版本也比较高&#xff0c;这样就容易出现之前项目不兼容问题&#xff0c;配置gradle可能会出现很多问题比较烦&#xff0c;所以干脆就用老版本的studio...

提示词实践总结

目录 一、要求创建SqlServer表&#xff08;ChatGpt&#xff09; 二、要求生成多层架构代码&#xff08;Cursor&#xff09; 三、要求修改方法返回值类型&#xff08;Cursor&#xff09; 四、要求修改方法入参&#xff08;Cursor&#xff09; 五、复杂的多表关联生成&#…...

【Elasticsearch】Filters聚合

Filters聚合的基本语法 Filters聚合是一种多桶聚合&#xff0c;用于将文档分组到多个桶中&#xff0c;每个桶对应一个过滤条件。以下是Filters聚合的基本语法和结构&#xff1a; 1.基本结构 json { "aggs": { "<aggregation_name>": { "filter…...

Java基础面试题50题

1&#xff0c;""空字符串的作用 package com.neuedu.nineteen;public class Test {public static void main(String[] args) {String s"";for (char i a; i < d; i) {ssi;//输出abc // sis;//输出cba}System.out.println(s);} }如题所示&…...

Django框架的全面指南:从入门到高级

Django框架的全面指南&#xff1a;从入门到高级 目录 引言Django简介安装与配置创建第一个Django项目Django的MVT架构模型&#xff08;Model&#xff09;视图&#xff08;View&#xff09;模板&#xff08;Template&#xff09;URL路由表单处理用户认证与权限Django Admin高级…...

c++继承

继承的概念和定义 继承的概念 继承 (inheritance) 机制是面向对象程序设计 使代码可以复用 的最重要的手段&#xff0c;它允许程序员在 保 持原有类特性的基础上进行扩展 &#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承 呈现了面向对象 程序设计的…...

【Linux系统】分页式存储管理

分页式存储管理 1、虚拟地址和页表的由来 思考一下&#xff0c;如果在没有虚拟内存和分页机制的情况下&#xff0c;每一个用户程序在物理内存上所对应的空间必须是连续的&#xff0c;如下图&#xff1a; 因为每一个程序的代码、数据长度都是不一样的&#xff0c;按照这样的映射…...

cmd执行mysql命令

安装mysql之后如果想使用cmd执行mysql命令&#xff0c;需要怎么操作呢&#xff0c;下面一起看一下。 安装mysql之后&#xff0c;如果直接去cmd窗口执行MySQL命令&#xff0c;窗口可能会提示mysql不是可执行命令。 需要配置系统的环境变量&#xff0c;将mysql的安装路径配置系…...

第一天:Linux内核架构、文件系统和进程管理

目录 Linux核心概念学习笔记一、Linux内核架构(一)内核的任务(二)实现策略(三)内核的组成部分(四)内核源文件目录结构二、Linux文件系统(一)文件系统架构(二)虚拟文件系统的数据结构三、Linux进程管理(一)进程相关概念(二)进程的层次结构(三)新进程创建机制(…...

QT:信号和槽

目录 1.概念 2.信号和槽的使用 2.1代码的方式使用 2.1.1.使用connect关联 2.2图形化界面的方式使用 2.2.1使用流程 2.2.2使用名字关联槽函数 3.自定义信号和槽函数 3.1自定义槽函数 3.2自定义信号 4.总结 1.概念 信号和槽是QT特有的一种机制&#xff0c;信号和槽都是…...

【Linux系统】线程:认识线程、线程与进程统一理解

一、更新认知 之前的认知 进程&#xff1a;一个执行起来的程序。进程 内核数据结构 代码和数据线程&#xff1a;执行流&#xff0c;执行粒度比进程要更细。是进程内部的一个执行分值 更新认识&#xff1a; a. 进程是承担分配系统资源的基本实体b. 线程是OS调度的基本单位 …...

蓝桥杯字串简写(二分)

输入 4 abababdb a b 输出 6 思路&#xff1a; 如果暴力&#xff0c;o(n**2)&#xff0c;超时&#xff0c;想到可以先与处理一下&#xff0c;记录c1出现的位置&#xff0c;再根据c2的位置用二分法看前面有多少个符合条件的c1。 why二分&#xff1a; 代码&#xff1a;一些…...

【C语言】指针详细解读3

1. 数组名的理解 我们使用指针一般访问数组内容时&#xff0c;我们可能会这样写&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&#xff0c;⽽…...

Python爬虫-如何正确解决起点中文网的无限debugger

前言 本文是该专栏的第45篇,后面会持续分享python爬虫干货知识,记得关注。 本文以起点中文网为例子,针对起点中文网使用控制台调试出现无限debugger的情况,要如何解决? 针对该问题,笔者在正文将介绍详细而又轻松的解决方法。废话不多说,下面跟着笔者直接往下看正文详细…...

畅游Diffusion数字人(15):详细解读字节跳动最新论文——音频+姿态控制人类视频生成OmniHuman-1

Diffusion models代码解读:入门与实战 前言:昨晚字节跳动刚发布了一篇音频+姿态控制人类视频生成OmniHuman-1的论文,效果非常炸裂,并且是基于最新的MM-DiT架构,今天博主详细解读一下这一技术。 目录 贡献概述 方法详解 音频条件注入 Pose条件注入 参考图片条件注入 …...

Windows图形界面(GUI)-QT-C/C++ - QT Dock Widget

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 一、概述 二、使用场景 1. 工具栏 2. 侧边栏 3. 调试窗口 三、常见样式 1. 停靠位置 2. 浮动窗口 3. 可关闭 4. 可移动 四、属性设置 1. 设置内容 2. 获取内容 3. 设置标题 …...

MIT AppInventor v2.74更新的内容

MIT v2.74更新的内容如下&#xff1a; 新的 UI 选择器提示 向菜单、调色板和设计视图添加键盘导航 更新至 Google Blockly 版本 10 按住 Shift 并拖动以选择多个块 当值被拖近并且没有空闲插槽时&#xff0c;文本等块会自动合并并展开列表 将块拖到边缘时工作区会自动滚动 新的…...

使用 Ollama 在 Windows 环境部署 DeepSeek 大模型实战指南

文章目录 前言Ollama核心特性 实战步骤安装 Ollama验证安装结果部署 DeepSeek 模型拉取模型启动模型 交互体验命令行对话调用 REST API 总结个人简介 前言 近年来&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用逐渐成为技术热点&#xff0c;而 DeepSeek 作为国产开…...

Hackmyvm whitedoor

简介 难度&#xff1a;简单 靶机地址&#xff1a; 环境 kali&#xff1a;192.168.194.9 靶机&#xff1a;192.168.194.24 扫描 nmap -sT -sV -A -T4 192.168.194.24 -p- -Pn 三个服务&#xff0c;ftp匿名登录、ssh连接以及web服务 ftp里面只有一个没用的README文件 访问…...