C# 多线程
概述
进程和线程
进程:指在系统中运行的一个应用程序。
线程:进程中的一个执行任务。一个进程至少有一个线程,一个进程可以有多个线程,多个线程可共享数据。
多线程
多线程:在一个程序中同时运行多个线程,每个线程执行各自的任务。
优点:使用多线程可以提高应用程序的响应能力,并利用多处理器或多核系统提高应用程序吞吐量。
缺点:死锁和争用条件
多线程适用场景:任务执行比较耗时的情况,也可以解决一些非常耗时的且长时间占用cpu资源的程序。
多线程的特点:
1、运行顺序不确定。
2、线程之间平行执行。
前台线程和后台线程
前台线程必须全部执行完,即使主线程关闭掉,这时进程仍然存活。后台线程在未执行完成时,如果前台线程关掉,则后台线程也会停掉。后台线程会随着主线程的关闭,而自动关闭。
补充
1、新创建的Thread默认是前台线程,可以通过设置IsBackground属性将其改为后台线程
2、线程池中的线程是后台线程
3、Task开启的线程是后台线程
4、前台线程适用场合:重要核心的,或者需要长时间等待的任务,例如:UI界面线程、发送数据的线程
5、后台线程适用:非核心且用于处理时间较短的任务适用。
Thread
Thread开启的线程默认都是后台线程
开启线程
//命名空间
using System.Threading;Thread thread = new Thread(SayHi);
void SayHi()
{Thread.Sleep(3000);Console.WriteLine("Hello World!");
}
thread.Start();
线程传参
//传递单个参数,thread.Start只支持传一个参数
Thread thread = new Thread((fileName) =>
{Console.WriteLine($"正在下载的文件名是{fileName}");
});
thread.Start("原神.apk");//传递多个参数 定义一个专门类,通过构造函数传参
//自定义类
class WriteInfo
{private string _name;private int _age;public WriteInfo(string name, int age){_name = name;_age = age;}public void ShowHumanInfo(){Console.WriteLine($"我叫{_name},今年{_age}岁");}
}public void ShowInfo(string name, int age)
{WriteInfo info = new WriteInfo(name, age);Thread t = new Thread(info.ShowHumanInfo);t.Start();
}
常用属性
属性 | 描述 |
CurrentThread | 获取当前正在运行的线程 |
IsAlive | 获取当前线程的执行状态 |
IsBackground | 某个线程是否为后台线程 |
IsThreadPoolThread | 线程是否属于托管线程池 |
ManagedThreadId | 获取当前托管线程的唯一标识符 |
Name | 获取或设置线程的名称 |
Priority | 线程的优先级可以影响线程的调用顺序 |
ThreadState | 当前线程的状态 |
线程状态
Aborted | 线程状态包括 AbortRequested 并且该线程现在已死,但其状态尚未更改为 Stopped |
AbortRequested | 已对线程调用了 Abort(Object) 方法,但线程尚未收到试图终止它的挂起的 ThreadAbortException |
Background | 线程正作为后台线程执行。 此状态可以通过设置 IsBackground 属性来控制 |
Running | 线程已启动且尚未停止 |
Stopped | 线程已停止 |
StopRequested | 正在请求线程停止 |
Suspended | 线程已挂起 |
SuspendRequested | 正在请求线程挂起 |
Unstarted | 尚未对线程调用 Start() 方法 |
WaitSleepJoin | 线程已被阻止。 这可能是调用 Sleep(Int32) 或 Join()、请求锁定或在线程同步对象上等待的结果 |
常用方法
方法 | 描述 |
Start | 开启线程 |
Abort | 终止线程 |
Sleep | 暂停线程一段时间 |
Join | 阻塞调用线程,直到某个线程终止 |
例子:等待Thread线程完成后进行后续操作
// 创建并启动新线程
Thread newThread = new Thread(() =>{Console.WriteLine("子线程开始运行");// 模拟耗时操作Thread.Sleep(2000);Console.WriteLine("子线程结束运行");});newThread.Start();// 等待子线程结束
newThread.Join();Console.WriteLine("主线程结束");
ThreadPool 线程池
1、线程池创建的线程默认都是后台线程,不能把池中的线程修改为前台线程,也不能修改线程池中优先级与名称。
2、线程池中的线程只能用于时间比较短的任务,如果后台线程需要长时间运行,则需要单独开启,不适合用线程池。
3、手动创建多个Thread线程可能会消耗较多性能,通过线程池可以提高效率。
4、缺点
ThreadPool
不支持线程的取消、完成、失败通知等操作;
ThreadPool
不支持线程执行的先后次序;
void ThreadPoolTest()
{ThreadPool.QueueUserWorkItem(GenFile, "原神.apk");ThreadPool.QueueUserWorkItem(GenFile, "王者荣耀.apk");ThreadPool.QueueUserWorkItem(GenFile, "蛋仔排队.apk");ThreadPool.QueueUserWorkItem(GenFile, "炉石传说.apk");
}void GenFile(object fileName)
{Thread.Sleep(3000);Console.WriteLine($"生成了文件{fileName}.txt");
}
Task 任务
Task开启的线程是后台线程
开启线程
//第一种方式
Task task = new Task(() =>
{});
task.Start();//第二种方式 Task.Run
Task task = Task.Run(() =>
{});//第三种方式 TaskFactory
TaskFactory taskFactory = new TaskFactory();
Task task = taskFactory.StartNew(() =>
{});//第四种方式 Task.Factory
Task task = Task.Factory.StartNew(() =>
{});
常用方法
方法 | 描述 |
Wait | 等待Task完成执行 |
WaitAny | 等待列表中任一Task完成执行,同步方法,会阻塞主线程 |
WaitAll | 等待列表中所有Task完成执行,同步方法,会阻塞主线程 |
WhenAny | 创建一个任务,该任务将在任一提供的任务完成时完成。异步方法,不会阻塞主线程 |
WhenAll | 创建一个任务,该任务将在数组中的所有 Task 对象完成时完成。异步方法,不会阻塞主线程 |
ContinueWith | 在任务完成后回调一个延续任务,参数是调用方的任务信息 |
//并行运行多个任务,等待任务都运行完后添加延续事件逻辑
List<Task> list = new List<Task>();
list.Add(Task.Run(() =>
{Console.WriteLine("开始做菜:");Thread.Sleep(3000);Console.WriteLine("做好素菜了!");}));list.Add(Task.Run(() =>
{Console.WriteLine("开始做菜:");Thread.Sleep(5000);Console.WriteLine("做好荤菜了!");}));Task.WhenAll(list).ContinueWith(t =>
{Console.WriteLine("菜都做好了,开饭吧!");});
WaitAll和WhenAll的区别?
1、Task.WaitAll 是一种同步方法,它会阻塞调用线程,直到所有提供的任务都已完成。当需要确保一组任务在继续之前已完成时,该方法很有用,但它以阻塞方式执行,这意味着调用 Task.WaitAll 的线程会被占用,直到所有任务都完成为止。
2、Task.WhenAll 是一种异步方法,当所有提供的任务都完成后,该方法将返回单个任务。与 Task.WaitAll 不同,它不会阻止调用线程。相反,它允许调用代码继续异步执行。
async/await + Task
async void TestAsync()
{await Task.Run(() =>{Console.WriteLine("开始做菜:");Thread.Sleep(3000);Console.WriteLine("做好素菜了!");});Console.WriteLine("开饭了!");
}
多线程隐患
争用条件
程序的结果取决于两个或更多个线程中的哪一个先到达某一特定代码块时出现的一种 bug。 多次运行程序会产生不同的结果,并且无法预测任何给定运行的结果。
public int gameState;
void DeadLock(){Thread t1 = new Thread(ChangeMyState);Thread t2 = new Thread(ChangeMyState);t1.Start();t2.Start();}void ChangeMyState(){while (true){gameState++;if (gameState == 100){Console.WriteLine("啊哦,好像出现问题了");}gameState = 100;}}
解决方案:用 lock 语句锁定在线程中共享的资源。
public int gameState;
public object objLock = new object();
void DeadLock()
{Thread t1 = new Thread(ChangeMyState);Thread t2 = new Thread(ChangeMyState);t1.Start();t2.Start();
}void ChangeMyState()
{lock (objLock){while (true){gameState++;if (gameState == 100){Console.WriteLine("啊哦,好像出现问题了");}gameState = 100;}}
}
死锁
如果使用lock不当,就会产生死锁情况!
描述:两个线程中的每一个线程都尝试锁定另外一个线程已锁定的资源时,就会发生死锁,两个线程都不能继续执行。(公共资源被多个线程争抢,导致一个线程永远等待另一个线程释放资源的异常情况)
死锁的四个必要条件:
1.互斥条件:资源一次只能被一个线程占用。
2.持有并等待条件:线程持有一个资源并等待获取其他资源。
3.不可剥夺条件:线程已获得的资源条件不能被强行剥夺,只能由线程自己释放。
4.循环等待条件:存在一组线程,每个线程都在等待下一线程持有的资源,形成一个环形等待。
死锁问题复现
object resourceA = new object();object resourceB = new object();int result;public void CheckDeadlock(){var thread1 = new Thread(Logic1);var thread2 = new Thread(Logic2);thread1.Start();thread2.Start();thread1.Join(); thread2.Join();Console.WriteLine(result);}public void Logic1(){lock (resourceA){Thread.Sleep(100);lock (resourceB){result += 1;}}}public void Logic2(){lock (resourceB){Thread.Sleep(100);lock (resourceA){result += 2;}}}
解决方案
方法一 调整锁的顺序
确保所有线程按相同的顺序请求锁。这可以打破死锁的循环等待条件。只要所有的线程都以相同的顺序请求资源,死锁就不会发生。
public void Logic1()
{lock (resourceA){Thread.Sleep(100);lock (resourceB){result += 1;}}
}public void Logic2()
{lock (resourceA){Thread.Sleep(100);lock (resourceB){result += 2;}}
}
方法二 锁的超时机制
使用Monitor.TryEnter 来设置获取锁的超时时间。如果超过指定时间无法获取锁,线程可以退出或执行其他操作。
public void Thread1Work()
{if (Monitor.TryEnter(resourceA, TimeSpan.FromSeconds(1))) // 尝试获取锁1,超时时间1秒{try{Console.WriteLine("Thread 1 acquired lock1");Thread.Sleep(100);if (Monitor.TryEnter(resourceB, TimeSpan.FromSeconds(1))) // 尝试获取锁2,超时时间1秒{try{result += 1;}finally{Monitor.Exit(resourceB); // 释放锁2}}else{Console.WriteLine("Thread 1 failed to acquire lock2, potential deadlock detected.");}}finally{Monitor.Exit(resourceA); // 释放锁1}}else{Console.WriteLine("Thread 1 failed to acquire lock1, potential deadlock detected.");}
}public void Thread2Work()
{if (Monitor.TryEnter(resourceB, TimeSpan.FromSeconds(1))) // 尝试获取锁2,超时时间1秒{try{Thread.Sleep(100);if (Monitor.TryEnter(resourceA, TimeSpan.FromSeconds(1))) // 尝试获取锁1,超时时间1秒{try{result += 2;}finally{Monitor.Exit(resourceA); // 释放锁1}}else{Console.WriteLine("Thread 2 failed to acquire lock1, potential deadlock detected.");}}finally{Monitor.Exit(resourceB); // 释放锁2}}else{Console.WriteLine("Thread 2 failed to acquire lock2, potential deadlock detected.");}
}
方法三 减少锁的持有时间
尽量缩小锁定的范围,确保只有在修改共享资源时才持有锁。这样可以减少锁竞争,降低死锁发生的机率。
参考链接
一文搞懂C#多线程、并发、异步、同步、并行 - biubiu12138 - 博客园
C# Task详解 - 五维思考 - 博客园
同步与异步:.NET 中的 Task.WaitAll 和 Task.WhenAll-CSDN博客
死锁(Deadlock)C#_c#死锁的原因及解决方法-CSDN博客
相关文章:
C# 多线程
概述 进程和线程 进程:指在系统中运行的一个应用程序。 线程:进程中的一个执行任务。一个进程至少有一个线程,一个进程可以有多个线程,多个线程可共享数据。 多线程 多线程:在一个程序中同时运行多个线程࿰…...
钉钉MAKE AI生态大会思考
1. 核心特性 1.1 底层模型开放 除原有模型通义千问外,新接入猎户星空、智普、MinMax、月之暗面、百川智能、零一万物。 1.2 AI搜索 AI搜索贯通企业和个人散落在各地的知识(聊天记录、文档、会议、日程、知识库、项目等),通过大模型对知识逻辑化,直接生成搜索的答案,并…...
自然语言处理:文本表示
介绍 大家好,博主又来给大家分享知识了。今天给大家分享的内容是自然语言处理中的文本表示。 在当今数字化信息爆炸的时代,自然语言处理作为人工智能领域的重要分支,发挥着越来越关键的作用。 而文本表示,则是自然语言处理的基…...
flutter 网络请求封装与json序列化与反序列化
一、用到的工具库 网络请求库 dioflutter pub add diojson序列化与反序列化库 json_annotation//终端直接键入下命令安装 flutter pub add json_annotation dev:build_runner dev:json_serializable二、返回结果泛化封装 以 https://www.wanandroid.com/ api 接口返回结果为例…...
生成网页链接二维码
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>生成二维码</title><script src"http…...
java关键字-instanceof
主要作用 A instanceof B主要判断以下三个内容(即左边的类型A能否转换为右边的B): 判断对象A是否是B类的对象;判断对象A实现了B接口;判断对象A是否继承了B类; A表示对象,B表示接口/类&#x…...
验证码识别:一文掌握手机验证码的自动化处理
文章目录 一、获取手机验证码1.1 通过短信接收验证码1.2 使用第三方短信接收服务1.3 使用ADB读取手机短信1.4 通过API获取验证码1.5 通过邮件接收验证码二、解析和提取验证码2.1 正则表达式提取2.2 JSON解析三、自动化输入验证码3.1 使用Selenium自动化Web应用3.2 使用Appium自…...
Uppy - 免费开源、功能强大的新一代 web 文件上传组件,支持集成到 Vue 项目
Uppy 这个优质的前端组件,可以解决几乎所有的文件上传问题,最近发布了 TS 重写的 4.0 新版本,实用性更强了。 Uppy 是一个 UI 外观时尚、模块化的 JavaScript 文件上传组件,这个组件可以与任何 web 技术栈集成,不仅轻…...
神经网络参数量计算
算一个只有两层的神经网络的参数量,我们需要考虑两层之间的连接权重和偏置项。以下是详细的计算步骤: 网络结构 输入层(第一层): 有 2 个神经元。 输出层(第二层): 有 3 个神经元。…...
如何为Java面试准备项目经验
1 提出问题 应届生朋友或Java程序员在找Java方面的工作时,一定会需要准备Java项目经验,但事实上不少求职者,是没有项目经验,或者只具有开源社区等的学习项目经验,这样的话,就很有可能在面试时无法有效地证…...
DeepSeek 与云原生后端:AI 赋能现代应用架构
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 1. 引言 在当今快速发展的互联网时代,云原生(Cloud Native)架构已成为后端开发的主流趋势。云…...
自定义异常
在 Java 中,自定义异常是指根据特定需求创建的异常类。通过自定义异常,可以更好地表示应用程序中的特定错误情况,并提供更清晰的错误信息。以下是关于自定义异常的详细介绍和实现方法: 一、为什么需要自定义异常? 明确…...
题解:洛谷 P2199 最后的迷宫
题目https://www.luogu.com.cn/problem/P2199 显然,数据最大 ,数组我们开不下,动态开数组。 对于每一个查询,从起点开始,走一步判断是否能看到火焰杯。 如果已经没法走了,直接拆墙,输出 Poor…...
JDK包含内容的正确说法及API文档下载
JDK包含内容的正确说法及API文档下载 正确说法:JDK包含JRE和JDK开发工具,而JRE主要包含JVM和核心类库。 因为 旧版 JRE(Java 8 及之前):确实包含 Java 插件(Applet) 和 Java Web Start…...
CTF-web: 查看python代码抽象语法树
抽象语法树(Abstract Syntax Tree,简称 AST)是源代码的树状表示,展示了代码的语法结构。在 Python 中,ast 模块可以帮助你解析和操作 Python 代码的 AST。 1. 使用 ast 模块解析 Python 代码 我们可以使用 ast.parse …...
前端学习——HTML
VSCode常用快捷键 代码格式化:ShiftAltF 向上或向下移动一行:AltUp或AltDown 快速复制一行代码:ShiftAltUp或者ShiftAltDown 快速替换:CtrlH HTML标签 文本标签 定义着重文字 定义粗体文字 定义斜体文字 加重语气 删除字 无特…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_open_file
ngx_open_file 定义在src/os/unix/ngx_files.h #define ngx_open_file(name, mode, create, access) \open((const char *) name, mode|create, access)#define NGX_FILE_RDONLY O_RDONLY #define NGX_FILE_WRONLY O_WRONLY #de…...
Window C++模拟单片机控制TFT屏幕和SD卡
因为每次都要做大量的测试,上传到单片机实在是太费事,所以写了这个模拟项目用来测试 很多方法我没有补充进去,因为太多了,如果有需要请自行补充 stdafx.h #pragma once#include<iostream> #include<atlimage.h> #in…...
记录一次FastDFS内部文件迁移过程
场景:dockr部署下的一个DFS环境,切换环境将原DFS内的所有文件全部迁移走,老版本的镜像包现不可使用,所以重新搭建并迁移外挂包下的所有文件 一、定位存储路径及备份 确定容器内存储路径 根据使用的Docker镜像不同࿰…...
【数据挖掘】Matplotlib
Matplotlib 是 Python 最常用的 数据可视化 库之一,在数据挖掘过程中,主要用于 数据探索 (EDA)、趋势分析、模式识别 和 结果展示。 📌 1. Matplotlib 基础 1.1 安装 & 导入 # 如果未安装 Matplotlib,请先安装 # pip instal…...
Python数据序列化技术:高效存储与传输的最佳实践
在现代软件开发中,数据序列化是一个关键环节,它允许我们将复杂的数据结构转换为可存储或可传输的格式,以便在不同的系统或程序之间共享和持久化。Python提供了多种数据序列化技术,每种技术都有其独特的性能优势和适用场景。本文将…...
大模型function calling:让AI函数调用更智能、更高效
大模型function calling:让AI函数调用更智能、更高效 随着大语言模型(LLM)的快速发展,其在实际应用中的能力越来越受到关注。Function Calling 是一种新兴的技术,允许大模型与外部工具或API进行交互,从而扩…...
HarmonyOS学习第12天:解锁表格布局的奥秘
表格布局初相识 不知不觉,我们在 HarmonyOS 的学习旅程中已经走到了第 12 天。在之前的学习里,我们逐步掌握了 HarmonyOS 开发的各种基础与核心技能,比如组件的基本使用、布局的初步搭建等,这些知识就像一块块基石,为我…...
基于 MetaGPT 自部署一个类似 MGX 的多智能体协作框架
MGX(由 MetaGPT 团队开发的 mgx.dev)是一个收费的多智能体编程平台,提供从需求分析到代码生成、测试和修复的全流程自动化功能。虽然 MGX 本身需要付费,但您可以通过免费服务和开源项目搭建一个类似的功能。以下是一个分步骤的实现…...
Cargo, the Rust package manager, is not installed or is not on PATH.
今天在Windows操作系统上通过pip 安装jupyter的时候遇到这个报错,Cargo, the Rust package manager, is not installed or is not on PATH.。 解决办法 官网:https://rustup.rs/# 下载:https://win.rustup.rs/x86_64 安装完成之后,…...
Spring AI:开启Java开发的智能新时代
目录 一、引言二、什么是 Spring AI2.1 Spring AI 的背景2.2 Spring AI 的目标 三、Spring AI 的核心组件3.1 数据处理3.2 模型训练3.3 模型部署3.4 模型监控 四、Spring AI 的核心功能4.1 支持的模型提供商与类型4.2 便携 API 与同步、流式 API 选项4.3 将 AI 模型输出映射到 …...
华为昇腾910b服务器部署DeepSeek翻车现场
最近到祸一台HUAWEI Kunpeng 920 5250,先看看配置。之前是部署的讯飞大模型,发现资源利用率太低了。把5台减少到3台,就出了他 硬件配置信息 基本硬件信息 按照惯例先来看看配置。一共3块盘,500G的系统盘, 2块3T固态…...
c++ 文件及基本读写总结
在 C 中,文件操作是非常重要的一部分,主要用于将数据存储到文件中,或者从文件中读取数据。C 标准库提供了fstream头文件,其中包含了用于文件操作的类,主要有ifstream(用于输入文件流,即从文件读…...
千峰React:组件与逻辑封装(上)
UI组件库及antd安装 UI组件库就是把页面的组件写好了,用的时候直接调用好了 进行一个安装的动作: 总之就是搭积木,可以调用里面写好的组件库拼接,也可以结合使用 antd布局和导航组件 组件总览 - Ant Design 这是通用部分 在用…...
Windows 10 远程桌面连接使用指南
目录 一、引言 二、准备工作 1、确认系统版本 2、服务器端设置 三、客户端连接 1、打开远程桌面连接程序 2、输入连接信息 3、输入登录凭证 4、开始使用远程桌面 四、移动端连接(以 iOS 为例) 1、下载安装应用 2、添加远程计算机 3、进行连接…...
使用Kali中的Metasploit生成木马控制Windows系统
使用Kali中的Metasploit生成木马控制Windows系统 (第九天 9.20) 一、kali及Metasploit kali基于debin的数字取证系统,上面集成很多渗透测试工具,其前身是BT5 R3(BrackTrack),在信息搜集方面发…...
Python与Web3.py库:构建去中心化应用的未来
Python与Web3.py库:构建去中心化应用的未来 在区块链的世界里,“去中心化”是最核心的理念之一,它赋予了用户更多的控制权和自由,消除了传统中心化系统中的单点故障和信任问题。而在这场技术革命中,Web3.0无疑是最受瞩…...
《Python实战进阶》No 8:部署 Flask/Django 应用到云平台(以Aliyun为例)
第8集:部署 Flask/Django 应用到云平台(以Aliyun为例) 2025年3月1日更新 增加了 Ubuntu服务器安装Python详细教程链接。 引言 在现代 Web 开发中,开发一个功能强大的应用只是第一步。为了让用户能够访问你的应用,你需…...
RAP: Efficient Text-Video Retrieval with Sparse-and-Correlated Adapter
标题:RAP:基于稀疏相关适配器的高效文本视频检索 原文链接:RAP: Efficient Text-Video Retrieval with Sparse-and-Correlated Adapter - ACL Anthology 发表:ACL-2024(NLP领域CCF A类) 摘要 文本-视频检索(TVR࿰…...
C++ ++++++++++
初始C 注释 变量 常量 关键字 标识符命名规则 数据类型 C规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存 整型 sizeof关键字 浮点型(实型) 有效位数保留七位,带小数点。 这个是保…...
用Python之requests库调用大型语言模型(LLM)API的流式输出与非流式输出比较
文章目录 1. 非流式输出与流式输出概述2. 非流式输出2.1 代码实例12.2 代码实例2 3. 流式输出3.1 流式输出的定义和作用3.2 流式输出适用的场景3.3 流式输出的实现方式与实现技术3.4 代码实例33.5 代码实例4 4. 小结 1. 非流式输出与流式输出概述 大模型收到输入后并不是一次性…...
JavaEE基础之- 过滤器和监听器Filter and Listener
目录 1. 过滤器 Filter 1.1. 初识过滤器 1.1.1. 过滤器概念 1.1.2. 过滤器例子 1.2. 过滤器详解 1.2.1. 过滤器生命周期 1.2.2. FilterConfig 1.2.3. FilterChain 1.1.4. 过滤器执行顺序 1.2.5. 过滤器应用场景 1.2.6. 过滤器设置目标资源 1.2.7. 过滤器总结 1.3 过滤…...
JavaAdv01——字节流和字符流
一、核心概念解析 1. 字节流(Byte Streams) 字节流家族: 输入流:InputStream(抽象类) FileInputStream ByteArrayInputStream BufferedInputStream 输出流:OutputStream FileOutputStream…...
HarmonyOS 5.0应用开发——多线程Worker和@Sendable的使用方法
【高心星出品】 文章目录 多线程Worker和Sendable的使用方法开发步骤运行结果 多线程Worker和Sendable的使用方法 Worker在HarmonyOS中提供了一种多线程的实现方式,它允许开发者在后台线程中执行长耗时任务,从而避免阻塞主线程并提高应用的响应性。 S…...
AI赋能传热学研究:创新与乐趣的深度融合
在科技飞速发展的当下,人工智能(AI)已逐渐渗透到各个领域,为不同行业带来了前所未有的变革与机遇。对于传热学研究而言,AI的介入不仅极大地提高了研究效率,还为研究者带来了全新的体验和思考。本文将深入探…...
Hive-03之传参、常用函数、explode、lateral view、行专列、列转行、UDF
大数据分析利器之hive 一、目标 掌握hive中select查询语句中的基本语法掌握hive中select查询语句的分组掌握hive中select查询语句中的join掌握hive中select查询语句中的排序 二、要点 1、hive的参数传递 1、Hive命令行 语法结构 hive [-hiveconf xy]* [<-i filename&…...
如何将Vue项目部署至 nginx
一、准备工作 1.确保安装了开发软件VS Code(此处可查阅安装 VS Code教程),确保相关插件安装成功 2.安装Node.js和创建Vue项目(此处可查阅安装创建教程) 3.成功在VS Code运行一个Vue项目(此处可查阅运行教…...
SwiftUI之状态管理全解析
文章目录 引言一、`@State`1.1 基本概念1.2 初始化与默认值1.3 注意事项二、`@Binding`2.1 基本概念2.2 初始化与使用2.3 注意事项三、`@ObservedObject`3.1 基本概念3.2 初始化与使用3.3 注意事项四、`@EnvironmentObject`4.1 基本概念4.2 初始化与使用4.3 注意事项五、`@Stat…...
Java-servlet(一)Web应用与服务端技术概念知识讲解
Java-servlet(一)Web应用与服务端技术概念知识讲解 前言一、Web 应用1.WEB CS BS 对比2.WEB 介绍3.web 与 http 的关系 二、servlet服务端技术1. 公共网关接口(CGI)2. servlet 是什么3.servlet 作用4. servlet 特性 前言 在当今时…...
多个pdf合并成一个pdf的方法
将多个PDF文件合并优点: 能更容易地对其进行归档和备份.打印时可以选择双面打印,减少纸张的浪费。比如把住宿发票以及滴滴发票、行程单等生成一个pdf,双面打印或者无纸化办公情况下直接发送给财务进行存档。 方法: 利用PDF24 Tools网站 …...
数据集笔记:新加坡停车费
data.gov.sg 该数据集包含 新加坡各停车场的停车费,具体信息包括: 停车场名称(Carpark):如 Toa Payoh Lorong 8、Ang Mo Kio Hub、Bras Basah Complex 等。停车区域类别(Category):…...
易错点abc
在同一个输入流上重复创建Scanner实例可能会导致一些问题,包括但不限于输入流的混乱。尤其是在处理标准输入(System.in)时,重复创建Scanner对象通常不是最佳实践,因为这可能导致某些输入数据丢失或者顺序出错。 为什么…...
leetcode第39题组合总和
原题出于leetcode第39题https://leetcode.cn/problems/combination-sum/description/题目如下: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以…...
【iOS】小蓝书学习(七)
小蓝书学习(七) 前言第47条:熟悉系统框架第48条:多用枚举块,少用for循环第50条:构建缓存使选用NSCache而非NSDictionary第51条:精简initialize与load的实现代码第52条:别忘了NSTimer…...
基于第三方SDK的Windows平台全功能RTMP|RTSP直播播放器深度解析
一、引言 在当今数字化时代,直播技术的应用场景不断拓展,从娱乐直播到教育、医疗、工业等多个领域,都对直播播放器的功能和性能提出了更高的要求。本文将介绍一款基于第三方SDK实现的全功能直播播放器,从技术实现、功能特点、用户…...