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

《Java 并发编程实践》阅读笔记(一):线程重要性

文章目录

  • 一. 并发历史
  • 二. 线程优势
  • 三. 线程带来的风险
    • 1. 安全性问题
    • 2. 活跃性问题
    • 3. 性能问题
  • 四. 线程无处不在
    • 示例1: Timer
    • 示例2: 远程方法调用(Remote Method Invocation, RMI)
    • 示例3: GUI 程序

一. 并发历史

  • 操作系统的出现

大型机时代, 没有操作系统, 一台主机只能执行一段预先规划好的程序. 对于昂贵并且稀有的计算机资源来说也是一种浪费, 这促使操作系统出现

操作系统的出现使得计算机每次能运行多个程序,并且不同的程序都在单独的进程中运行

  • 进程的出现

资源利用率公平性以及便利性等因素, 促使进程出现

操作系统为各个独立执行的进程分配各种资源, 如果需要的话,在不同的进程之间可通过粗粒度的通信机制来交换数据

  1. 资源包括:内存,文件句柄, 以及 安全证书
  2. 通信机制包括:套接字、信号处理器、共享内存、信号量, 以及 文件 等。
  • 串行编程模型

在早期的分时系统中,每个进程相当于一台虚拟的冯·诺依曼计算机

它拥有存储指令和数据的内存空间,根据机器语言的语义以串行方式执行指令,并通过一组I/O指令与外部设备通信。

对每条被执行的指令,都有相应的“下一条指令”​,程序中的控制流是按照指令集的规则来确定的。当前,几乎所有的主流编程语言都遵循这种串行编程模型,并且在这些语言的规范中也都清晰地定义了在某个动作完成之后需要执行的“下一个动作”​。

串行编程模型的优势在于其直观性和简单性,因为它模仿了人类的工作方式:每次只做一件事情,做完之后再做另一件。

  • 现实世界中的动作可以被进一步抽象为一组粒度更细的动作

例如喝早茶的动作: 首先起床,穿上睡衣,然后下楼,喝早茶。

喝早茶的动作可以被进一步细化为:打开橱柜,挑选喜欢的茶叶,将一些茶叶倒入杯中,看看茶壶中是否有足够的水,如果没有的话加些水,将茶壶放到火炉上,点燃火炉,然后等水烧开等等。

在最后一步等水烧开的过程中包含了一定程度的异步性。当正在烧水时,你可以干等着,也可以做些其他事情,例如开始烤面包(这是另一个异步任务)或者看报纸,同时留意茶壶水是否烧开。

茶壶和面包机的生产商都很清楚:用户通常会采用异步方式来使用他们的产品,因此当这些机器完成任务时都会发出声音提示。但凡做事高效的人,总能在串行性与异步性之间找到合理的平衡,对于程序来说同样如此。

  • 线程出现

促使进程出现的因素, 同样也促使着线程的出现。

线程允许在同一个进程中同时存在多个程序控制流。线程会共享进程范围内的资源,例如内存句柄和文件句柄

但每个线程都有各自的 1.程序计数器(Program Counter)、2.栈, 以及 3.局部变量等。

线程还提供了一种直观的分解模式来充分利用多处理器系统中的硬件并行性,而在同一个程序中的多个线程也可以被同时调度到多个CPU上运行

线程也被称为轻量级进程。在大多数现代操作系统中,都是以线程为基本的调度单位,而不是进程。

如果没有明确的协同机制,那么线程将彼此独立执行。由于同一个进程中的所有线程都将共享进程的内存地址空间,因此这些线程都能访问相同的变量并在同一个堆上分配对象,这就需要实现一种比在进程间共享数据粒度更细的数据共享机制。如果没有明确的同步机制来协同对共享数据的访问,那么当一个线程正在使用某个变量时,另一个线程可能同时访问这个变量,这将造成不可预测的结果。

二. 线程优势

  • 同类合并

只需要执行一种类型的任务(例如修改12个错误)时,在时间管理方面比执行多种类型的任务要简单。

当只有一种类型的任务需要完成时,只需埋头工作,直到完成所有的任务(或者你已经精疲力尽)​,你不需要花任何精力来琢磨下一步该怎么做。而另一方面,如果需要完成多种类型的任务,那么需要管理不同任务之间的优先级和执行时间,并在任务之间进行切换,这将带来额外的开销。

  • 异步事件简化处理

远程调用如果为每个连接都分配其各自的线程并且使用同步I/O,会降低这类程序的开发难度, 但读操作将一直阻塞,直到有数据到达。在单线程应用程序中,这不仅意味着在处理请求的过程中将停顿,而且还意味着在这个线程被阻塞期间,对所有请求的处理都将停顿。为了避免这个问题,单线程服务器应用程序必须使用非阻塞I/O,这种I/O的复杂性要远远高于同步I/O,并且很容易出错。

然而,如果每个请求都拥有自己的处理线程,那么在处理某个请求时发生的阻塞将不会影响其他请求的处理。

上面只是举一个简单的处理方法. 早期的操作系统会将进程可创建的线程数量限制在一个较低的阈值,大约在数百个(甚至更少)左右。

因此,操作系统提供了一些高效的方法来实现多路I/O,例如Unix的select和poll等系统调用,要调用这些方法,Java类库需要获得一组实现非阻塞I/O的包(java.nio)

然而,在现代操作系统中,线程数量已得到极大的提升,这使得在某些平台上,即使有更多的客户端,为每个客户端分配一个线程也是可行的

  • 更灵敏的 GUI

大多数GUI框架都是单线程子系统,通常通过一个“主事件循环(Main Event Loop)” 来间接地执行应用程序的所有代码。

如果在主事件循环中调用的代码需要很长时间才能执行完成,那么用户界面就会“冻结”​,直到代码执行完成。这是因为只有当执行控制权返回到主事件循环后,才能处理后续的用户界面事件。

在事件线程中执行的任务如果都是短暂的,那么界面的响应灵敏度就较高,因为事件线程能够很快地处理用户的动作。如果用户在执行这类任务时触发了某个动作,那么必须等待很长时间才能获得响应,因为事件线程要先执行完该任务。更糟糕的是,即使界面上包含了“取消”按钮,也无法取消这个长时间执行的任务,因为事件线程只有在执行完该任务后才能响应“取消”按钮的点击事件。

如果将这个长时间运行的任务放在一个单独的线程中运行,那么事件线程就能及时地处理界面事件,从而使用户界面具有更高的灵敏度。(现代的主事件循环大多处于GUI工具的控制下并在其自己的线程中运行,采用一个事件分发线程(Event Dispatch Thread, EDT), 而不是在应用程序的控制下)

三. 线程带来的风险

风险之一: 难以分析, 因为它们依赖于不同线程的事件发生时序,因此在开发或者测试中并不总能够重现

1. 安全性问题

在没有充足同步的情况下,多个线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果

产生未预测的结果, 比如钱算错, 程序保证不了正确性

安全性的含义是 “永远不发生糟糕的事情

2. 活跃性问题

活跃性则关注于另一个目标,即 “某件正确的事情最终会发生”​。当某个操作无法继续执行下去时,就会发生活跃性问题。

死锁 / 饥饿. 例如,如果线程A在等待线程B释放其持有的资源,而线程B永远都不释放该资源,那么A就会永久地等待下去。

单线程-串行程序也会有, 比如无意中造成的死循环,从而使循环之后的代码无法得到执行

在开发并发代码时,注意线程安全性是不可破坏的。安全性不仅对于多线程序很重要,对于单线程程序同样重要。

3. 性能问题

解决完活跃性问题, 意味着某件正确的事情最终会发生. 但发生了但却不够好, 这就是性能问题,因为我们通常希望正确的事情尽快发生。

性能问题包括多个方面,例如:

  1. 服务时间过长
  2. 响应不灵敏
  3. 吞吐率过低
  4. 资源消耗过高
  5. 可伸缩性较低
  6. 等等。

与安全性和活跃性一样,在多线程程序中不仅存在与单线程程序相同的性能问题,而且还存在由于使用线程而引入的其他性能问题。

  • 关注点

使用线程本质上是想提升性能, 但使用后却额外增加了性能问题 (上下文切换, 线程调度, 同步机制抑制编译器优化等), 这就是关注点.

  • 上下文切换 (Context Switch)

无论如何,线程总会带来某种程度的运行时开销。在多线程程序中,当线程调度器临时挂起活跃线程并转而运行另一个线程时,就会频繁地出现上下文切换操作 (Context Switch),下面这种操作将带来极大的开销:

  1. 保存和恢复执行上下文,丢失局部性,并且CPU时间将更多地花在线程调度而不是线程运行上。
  2. 当线程共享数据时,必须使用同步机制,而这些机制往往会抑制某些编译器优化,使内存缓存区中的数据无效
  3. 增加共享内存总线的同步流量。

所有这些因素都将带来额外的性能开销

四. 线程无处不在

  • 框架中会创建线程. 在被这些线程调用的代码, 同样也必须是线程安全的
  • 每个 Java 应用程序都会使用线程. JVM 启动后会创建后线程, 来为 JVM 内部任务 (垃圾收集, 终结操作等) 服务
  • 并发不局限, 线程的安全性需求会在程序中蔓延. 当某个框架在应用程序中引入并发性时,通常不可能将并发性仅局限于框架代码. (例如: 框架会回调(Callback)应用代码,而这些代码将访问应用程序的状态) 对线程安全性的需求也不局限于被调用的代码,而是延伸到访问到程序状态的所有代码路径

框架通过在框架线程中调用应用程序代码将并发性引入到程序中。在代码中将不可避免地访问应用程序状态,因此所有访问这些状态的代码路径都必须是线程安全的。

示例1: Timer

Timer 类的作用是使任务在稍后的时刻运行,或者运行一次,或者周期性地运行。

引入Timer可能会使串行程序变得复杂,因为TimerTask将在Timer管理的线程中执行,而不是由应用程序来管理。

如果某个TimerTask访问了应用程序中其他线程访问的数据,那么不仅TimerTask需要以线程安全的方式来访问数据,其他类也必须采用线程安全的方式来访问该数据。通常实现这个目标,最简单的方式是确保TimerTask访问的对象本身是线程安全的,从而就能把线程安全性封装在共享对象内部

示例2: 远程方法调用(Remote Method Invocation, RMI)

RMI 使代码能够调用在其他JVM中运行的对象。当通过RMI调用某个远程方法时,传递给方法的参数必须被打包(也称为列集[Marshaled]​)到一个字节流中,通过网络传输给远程JVM,然后由远程JVM拆包(或者称为散集[Unmarshaled]​)并传递给远程方法。

当RMI代码调用远程对象时,这个调用将在哪个线程中执行?你并不知道,但肯定不会在你创建的线程中,而是将在一个由RMI管理的线程中调用对象。RMI会创建多少个线程?同一个远程对象上的同一个远程方法会不会在多个RMI线程中被同时调用? (会的) 远程对象必须注意两个线程安全性问题:

  1. 正确地协同在多个对象中共享的状态
  2. 对远程对象本身状态的访问(由于同一个对象可能会在多个线程中被同时访问)​

与Servlet相同,RMI 对象应该做好被多个线程同时调用的准备,并且必须确保它们自身的线程安全性。

示例3: GUI 程序

GUI应用程序的一个固有属性是异步性, 例如有专门的名词 UI 线程 (或 事件线程). 用户可以在任意时刻选择一个菜单项或者按下一个按钮,应用程序就会及时响应,即使应用程序当时正在执行其他的任务

Swing和AWT很好地解决了这个问题,它们创建了一个单独的线程来处理用户触发的事件,并对呈现给用户的图形界面进行更新。

Swing的一些组件并不是线程安全的,例如JTable。相反,Swing程序通过将所有对GUI组件的访问局限在事件线程中以实现线程安全性。

如果某个应用程序希望在事件线程之外控制GUI,那么必须将控制GUI的代码放在事件线程中运行。当用户触发某个UI动作时,在事件线程中就会有一个事件处理器被调用以执行用户请求的操作。如果事件处理器需要访问由其他线程同时访问的应用程序状态(例如编辑某个文档)​,那么这个事件处理器,以及访问这个状态的所有其他代码,都必须采用一种线程安全的方式来访问该状态

相关文章:

《Java 并发编程实践》阅读笔记(一):线程重要性

文章目录 一. 并发历史二. 线程优势三. 线程带来的风险1. 安全性问题2. 活跃性问题3. 性能问题 四. 线程无处不在示例1: Timer示例2: 远程方法调用(Remote Method Invocation, RMI)示例3: GUI 程序 一. 并发历史 操作系统的出现 大型机时代, 没有操作系统, 一台主机只能执行一…...

算法思想之分治-归并

欢迎拜访:雾里看山-CSDN博客 本篇主题:算法思想之分治-归并 发布时间:2025.4.17 隶属专栏:算法 目录 算法介绍核心思想与步骤时空复杂度分析C代码实现关键特性与优化 例题排序数组题目链接题目描述算法思路代码实现 交易逆序对的总…...

Vue基础(5)_事件修饰符

事件修饰符 Vue中的事件修饰符: 1、prevent:阻止默认事件(常用)。 2、stop:阻止事件冒泡(常用)。 3、once:事件只触发一次(常用)。 4、capture:使用事件的捕获模式。 5、self:只有event.target是当前操作的…...

网络编程 - 1

目录 为什么需要网络编程? —— 丰富的网络资源 什么是网络编程 网络编程中的基本概念 发送端和接收端 请求和相应 客户端和服务端 常见的客户端服务端模型 Socket 套接字 概念 分类 解释 有连接 / 无连接 可靠传输 / 不可靠传输 面向字节流 / 面向数…...

github | 仓库权限管理 | 开权限

省流版总结: github 给别人开权限:仓库 -> Setting -> Cllaborate -> Add people GitHub中 将公开仓库改为私有:仓库 -> Setting -> Danger Zone(危险区) ->Change repository visibility( 更改仓…...

【系统搭建】DPDK关键概念与l2fwd源码解析

DPDK(Data Plane Development Kit)是一套用于高性能网络数据面处理的开发框架,其核心设计在于绕过内核协议栈,它提供了一个用户空间下的高效数据包处理库函数,可以用于快速开发高性能的网络应用程序,如网络…...

【Qt】初识Qt(一)

目录 一、Qt的背景二、认识Qt项目 一、Qt的背景 关于客户端开发: 客户端开发的重要任务,是编写和用户交互的界面,和用户交互的界面有两种风格: TUI:命令行界面,也叫终端界面GUI:图形化界面 Q…...

Django REST framework 并结合 `mixin` 的示例

下面为你提供一个使用 Django REST framework 并结合 mixin 的示例,该示例将实现一个简单的图书管理 API。 项目需求 我们要创建一个图书管理系统的 API,支持对图书信息的创建、读取、更新和删除操作。 实现步骤 1. 项目初始化 首先,确保你已经安装了 Django 和 Django…...

《前端性能优化秘籍:打造极致用户体验》

在当下,网站和应用的性能表现直接关乎用户去留。快速加载、流畅交互的页面能让用户沉浸其中,反之,缓慢的响应速度则会让他们毫不犹豫地离开。对于前端开发者而言,性能优化不仅是技术追求,更是提升用户体验、增强产品竞…...

数据结构与算法学习导航

目录 指导思想资料总结代码随想录hello-algoOI-WIKI 一名麻瓜的刷leetcode的简单概述。 在这里对过去的自己说: 如果你相信算法有用你就刷刷leetcode,如果不相信面试会让你相信。 当然,现在我确实认为算法和数据结构有用,leetcode也有用。 …...

【Python】用Python写一个俄罗斯方块玩玩

【Python】用Python写一个俄罗斯方块玩玩 一、引言1.成品效果展示 二、思考准备1.思考设计2.代码设计2.1 游戏页面2.2 控件设计2.2.1 方块生成2.2.2 方块碰撞2.2.3 方块消融2.2.4 游戏主循环2.2.5 游戏窗口 三、游戏完整版 一、引言 今日看到侄子在玩游戏,凑近一看…...

nginx中的代理缓存

1.缓存存放路径 对key取哈希值之后,设置cache内容,然后得到的哈希值的倒数第一位作为第一个子目录,倒数第三位和倒数第二位组成的字符串作为第二个子目录,如图。 proxy_cache_path /xxxx/ levels1:2 2.文件名哈希值...

【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02

博主简介:努力学习的22级计算机科学与技术本科生一枚🌸博主主页: Yaoyao2024往期回顾:【深度学习】你真的理解张量了吗?|标量、向量、矩阵、张量的秩|01每日一言🌼: “脑袋想不明白的,就用脚想”…...

20.3 使用技巧3

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 20.3.5 禁止追加行与禁止删除行 通常情况下DataGridView最末一行是空白行,在此行单元格输入数据就可以追加新行。如果需要…...

使用代理IP提取数据的步骤是什么?代理IP如何提高爬虫采集效率?

在当今大数据时代,网络爬虫已成为获取互联网信息的重要手段。然而,许多网站为了防止数据被过度抓取,会设置反爬机制,如IP封禁、访问频率限制等。这时,使用代理IP就成为了一种有效的解决方案。本文将详细介绍使用代理IP…...

探索关系型数据库 MySQL

目录 引言 一.SQL的基本操作 1.数据库是什么? 什么是SQL? 1.1.OLTP 1.2.OLAP 1.3.SQL 1.4.DQL 1.5.DML 1.6.DDL 1.7.DCL 1.8.TCL 1.9.数据库术语 2.MySQL体系结构 2.1.连接者 2.2.MySQL 内部连接池 2.3.管理服务和工具组件 2.4.SQL接口 …...

Redis--事务

目录 一、事务介绍 二、事务操作 2.1 MULTI 2.2 EXEC 2.3 DISCARD 2.4 WATCH 2.5 UNWATCH 一、事务介绍 Redis 的事务和 MySQL 的事务概念上是类似的. 都是把一系列操作绑定成⼀组. 让这⼀组能够批量执行. 但是注意体会 Redis 的事务和 MySQL 事务的区别: 1.弱化的原子性…...

【Windows上配置Git环境】

在Windows上配置Git环境可以按照以下步骤进行: 1. 下载Git 打开浏览器,访问Git官方网站https://git-scm.com/downloads。在下载页面中,找到适用于Windows的下载链接,根据你的系统是32位还是64位选择相应的安装包进行下载 。 2.…...

揭秘大数据 | 23、软件定义网络

软件定义网络将网络的边缘从硬件交换机推进到了服务器里面,将服务器和虚拟机的所有部署、管理的职能从原来的系统管理员网络管理员的模式变成了纯系统管理员的模式,让服务器的业务部署变得简单,不再依赖于形态和功能各异的硬件交换机&#xf…...

前端api(请求后端)简易template

微信小程序 API 模块模板 基本 API 模块结构 /*** 示例API模块*/ const api require(../api); const config require(../../config/index);// 示例API对象 const exampleApi {// API方法定义... };// 导出模块 module.exports exampleApi;标准 RESTful 请求方法 获取列表…...

【力扣】重排链表

重排链表 代码 class Solution { public:void reorderList(ListNode* head) {//当链表只有一个节点或两个节点时直接返回空,不用重排if (head->next NULL || head->next->next NULL) return;//1. 进行分割链表ListNode* fast head, *slow head;ListNode* end1 N…...

选 Hibernate 还是 MyBatis?全方位差异解读

Hibernate 和 MyBatis 都是 Java 开发中用于处理数据库操作的持久化框架,不过它们在实现技术上存在诸多差异,下面从多个方面进行对比: 1. 映射机制 Hibernate:采用全自动的对象关系映射(ORM)机制&#xf…...

SvelteKit 最新中文文档教程(21)—— 最佳实践之图片

前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...

类和对象(下篇)(详解)

【本节目标】 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5. 再次理解封装 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 #include <iostream> using name…...

win10下github libiec61850库编译调试sntp_example

libiec61850 https://github.com/mz-automation/libiec61850 v1.6 简介 libiec61850 是一个开源&#xff08;GPLv3&#xff09;的 IEC 61850 客户端和服务器库实现&#xff0c;支持 MMS、GOOSE 和 SV 协议。它使用 C 语言&#xff08;根据 C99 标准&#xff09;实现&#xf…...

【HDFS入门】HDFS高可用性与容错机制深度解析

目录 引言 1 HDFS高可用架构实现 1.1 基于QJM的NameNode HA架构 1.2 QJM vs NFS实现对比 2 故障切换流程与ZooKeeper作用 2.1 自动故障转移流程 2.2 状态转换机制 3 数据恢复与副本管理 3.1 DataNode故障处理流程 4 快照与数据保护机制 4.1 HDFS快照架构 4.2 快照使…...

Qt QML实现Windows桌面歌词动态播放效果

前言 使用Qt5.15.2&#xff0c;QML实现简单的歌词动态播放效果。 效果图如下&#xff1a; 注&#xff1a;这里只是为了演示播放效果&#xff0c;并未真正加载音频进行播放。可以在此基础上进行扩展。 正文 关键代码 QML部分 import QtQuick 2.15 import QtQuick.Window 2.…...

Qt GUI 库总结

Qt GUI 库总结 Qt GUI 库&#xff08;QtGui&#xff09;是 Qt 框架中负责图形用户界面&#xff08;GUI&#xff09;开发的核心模块。本文将一步步详解 QtGui&#xff0c;从基础入门到高级应用&#xff0c;帮助你全面掌握其功能。以下内容包括环境配置、基本功能、核心特性及进…...

[dp16_两个数组] 通配符匹配 | 交错字符串 | 两个字符串的最小ASCII删除和

目录 1.通配符匹配 题解 2.交错字符串 题解 3.两个字符串的最小ASCII删除和 1.通配符匹配 链接&#xff1a;44. 通配符匹配 给你一个输入字符串 (s) 和一个字符模式 (p) &#xff0c;请你实现一个支持 ? 和 * 匹配规则的通配符匹配&#xff1a; ? 可以匹配任何单个字…...

记录一次生产中mysql主备延迟问题处理

登录库&#xff1a; mysql -uXXXX -pXXXX -P3306 -hXXXXXX -A 备库上执行&#xff1a;show slave status\G 查看 seconds_Behind_Master&#xff0c;延迟 2705s&#xff0c;而且还一直在增加。 SHOW CREATE TABLE proc_i_income_temp; -- 查看表的结构 show index from proc…...

【计算机视觉】OpenCV实战项目-AdvancedLaneDetection 车道检测

AdvancedLaneDetection 项目解析 项目概述项目结构功能和步骤依赖项使用方法项目特点改进建议结论运行项目1. 克隆项目仓库2. 安装依赖项创建虚拟环境&#xff08;可选&#xff09;激活虚拟环境安装依赖项 3. 准备数据4. 运行项目5. 调整配置&#xff08;可选&#xff09;6. 查…...

趣味编程之分布式系统:负载均衡的“雨露均沾“艺术

#此篇文章由Deepseek大力支持&#x1f60b; 凌晨三点&#xff0c;西二旗某火锅店后厨—— “羊肉卷走3号桌&#xff01;” “肥牛卷去7号&#xff01;” “虾滑优先给VIP区&#xff01;” 我蹲在传菜口的监控屏幕前&#xff0c;看着机器人服务生们忙而不乱地穿梭。突然间&am…...

移植firefly core-1126-jd4官方sdk源码到其他rv1126板卡时 kernel启动中失去响应问题解决

问题背景 在项目中采用firefly core-1126-jd4的sdk适配其他rv1126板卡遇到kernel启动中无响应。串口能看到运行到usb、mmc等模块驱动流程&#xff0c;但之后就打印&#xff0c;通过追加打印确认usb、mmc模块的init已经执行完&#xff0c;怀疑是执行其他某个静态编译进kernel的…...

Oracle表的别名不能用as,列的别名可以用as

在 Oracle 数据库中&#xff0c;‌表的别名‌和‌列的别名‌在使用 AS 关键字时确实有不同规则&#xff0c;以下是详细说明&#xff1a; 1. 表的别名&#xff08;Table Alias&#xff09;‌ ‌不支持 AS 关键字‌&#xff0c;直接跟在表名后即可。‌语法示例‌&#xff1a; S…...

对于“人工智能+教育”的一些思考

如果说人工智能当下最合适的落地场景&#xff0c;那么进入课堂这件事一定是排在靠前的位置。从当下的趋势来看&#xff0c;人工智能进入课堂已经不是设想&#xff0c;而是我们必须要去做的一件事了。 方向有了&#xff0c;但是问题是&#xff1a;人工智能进入中小学课堂到底应该…...

Android audio系统四 audiopolicy与audioflinger播放和录音

播放/录音在上层是通过AudioTrack与AudioRecord实现的。通过一张简单的流程图查看audiopolicy与audioflinger进行了哪些操作...

【Pandas】pandas DataFrame xs

Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前几行DataFrame.at快速访问和修改 DataFrame 中单个值的方法DataFrame.iat快速访问和修改 DataFrame 中单个值的方法DataFrame.loc用于基于标签&#xff08;行标签和列标签&#…...

开源一体化白板工具Drawnix本地部署打造毫秒级响应的远程协作空间

文章目录 前言1、什么是Drawnix&#xff1f;2、部署Drawnix的环境和步骤3、Drawnix的简单使用方法4、安装cpolar内网穿透5、配置公网地址6、配置固定二级子域名公网地址总结 前言 想象一下&#xff0c;你是一个创意满满的设计师&#xff0c;脑海中涌现出无数灵感火花。你急忙打…...

UMAEA论文阅读

Preliminaries MMKG为一个五元组G{E, R, A, V, T}&#xff0c;其中E、R、A和V分别表示实体集、关系集、属性集和图像集。 T⊆ERE是关系三元组集。 给定两个MMKG G1 {E1, R1, A1, V1, T1} 和 G2 {E2, R2, A2, V2, T2}&#xff0c; MMEA旨在识别每个实体对&#xff08;e1…...

捕鱼船检测数据集VOC+YOLO格式2105张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2105 标注数量(xml文件个数)&#xff1a;2105 标注数量(txt文件个数)&#xff1a;2105 …...

R4打卡——pytorch实现LSTM预测火灾

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 1.检查GPU import torch.nn.functional as F import numpy as np import pandas as pd import torch from torch import nndata pd.read_csv("da…...

【数字图像处理】图像增强

图像增强——频率域分析 卷积定理 函数卷积的傅里叶变换是函数傅里叶变换的乘积&#xff0c;即&#xff1a;一个域中的卷积相当于另一个域中的乘积 F(x)为傅里叶变换 傅里叶 傅里叶级数&#xff1a;任何周期函数都可以用不同频率的正弦函数和余弦函数构成的无穷级数来表示。 正…...

Windows平台用vistual studio 2017打包制作C++动态库

1. 创建库项目 打开 Visual Studio 2017&#xff0c;选择 文件 → 新建 → 项目。选择 Visual C → Windows 桌面 → 动态链接库 (DLL) 或 静态库 (LIB)。 动态库 (DLL)&#xff1a;生成 .dll 和 .lib&#xff08;导出符号表&#xff09;。静态库 (LIB)&#xff1a;生成 .lib&…...

QT日历控件重写美化

效果图 先放一个效果图以供大家参考&#xff0c;大家可以根据自己需要的效果来调整自己的控件&#xff0c;日历控件实现了自定义日历选择框&#xff0c;设置了表头颜色&#xff0c;设置日历当天重要事件提醒功能。 设置表头样式 setVerticalHeaderFormat(QCalendarWidget::NoV…...

单细胞分析读取处理大型数十万细胞的数据集的优化

单细胞分析读取处理大型数十万细胞的数据集的优化 背景简介 有朋友反映用自己的笔记本电脑在分析比较大的单细胞数据集的时候&#xff0c;比如细胞数量有十万个以上甚至几十万个的时候&#xff0c;可能自己的电脑的内存32G或64G都不够用&#xff0c;一般来说&#xff0c;做生…...

HTTP 3.0 协议的特点

HTTP/3 是互联网传输协议的一次重要升级&#xff0c;相较于 HTTP/2&#xff0c;它引入了多项显著改进和新特性。 基于 QUIC 协议&#xff1a; HTTP/3 采用了 QUIC&#xff08;Quick UDP Internet Connections&#xff09;作为底层传输协议&#xff0c;QUIC 基于 UDP&#xff0…...

电子电器架构 --- 下一代汽车电子/电气(E/E)架构

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 周末洗了一个澡&#xff0c;换了一身衣服&#xff0c;出了门却不知道去哪儿&#xff0c;不知道去找谁&am…...

08软件测试需求分析案例-删除用户

删除用户是后台管理菜单的一个功能模块&#xff0c;只有admin才有删除用户的权限。不可删除admin。 1.1 通读文档 通读需求规格说明书是提取信息&#xff0c;提出问题&#xff0c;输出具有逻辑、规则、流程的业务步骤。 信息&#xff1a;此功能应为用户提供确认删除的功能。…...

await 在多线程,子线程中的使用

await 在多线程,子线程中的使用 await self.send_reply(user, user, user, auto_content, reply) 这行代码是在一个异步函数里调用类的实例方法 send_reply 代码含义 1. await 关键字 在 Python 的异步编程里,await 关键字的作用是暂停当前异步函数的执行,直到 await 后…...

NLP高频面试题(四十六)——Transformer 架构中的位置编码及其演化详解

引言 Transformer 模型(Vaswani 等人,2017)在序列建模中取得了革命性突破,利用自注意力机制实现了并行的序列处理。然而,Transformer 本身对序列的顺序信息不敏感:输入序列元素在自注意力中是无排列的(Permutation-invariant)。换言之,Transformer 缺乏像 RNN 那样的…...