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

C#基础——线程(线程池、线程锁、线程抢占、多线程)

线程

进程(Process)是由操作系统分配资源并执行的一个独立的程序实,属于Windows的概念,进程结束就表示程序关闭了。

线程(Thread)是程序中执行的最小单位。一个线程代表了一个独立的执行流,可以独立运行,执行特定的任务。每个应用程序至少有一个线程,即主线程,用于执行主要的程序代码。

进程可以包含多个线程,但是主线程只有一个,如果遇到繁琐的任务,可以开辟线程,开辟出来的线程叫做分线程

static void Main(string[] args) { //Main是主函数Console.WriteLine("这句代码是在主线程中执行的");//设置主线程名称//Thread.CurrentThread 获取当前正在运行的线程Thread.CurrentThread.Name = "Main";Console.WriteLine(Thread.CurrentThread.Name); //Main
}

Thread 类 :表示一个操作系统级别的线程,允许你在应用程序中创建、控制和管理线程。

创建分线程的第一种方式

//创建线程的第一种方法设置线程委托
//1、设置线程委托(目的是为了告诉线程应该执行的耗时任务是谁)
ThreadStart childref = new ThreadStart(Promothod);
//2、把委托交给Thread
Thread childThread = new Thread(childref);
//3、可以分线程Thread分配一个名字,便于甄别
childThread.Name = "分线程1";
// Start 执行分线程
childThread.Start();//定义一个函数
public static void Promothod() {Console.WriteLine(Thread.CurrentThread.Name);
}

创建线程的第二种方式(箭头函数)

Thread thread2 = new Thread(() => {Console.WriteLine("这是分线程2");
});
thread2.Start();

Sleep 线程休眠

Thread thread3 = new Thread(() => {Console.WriteLine("这是分线程3,开始睡觉~耗时3秒");//Sleep 线程休眠的毫秒数Thread.Sleep(3000); Console.WriteLine("睡醒了,开始敲代码了。");
});
thread3.Start();//Abort 线程启动之后,使用完毕最好要销毁掉thread3.Abort();

带有参数的委托类(使用线程委托方法)

//带有参数的委托类,参数必须是object类型,否则会报错
ParameterizedThreadStart ptstart = new ParameterizedThreadStart(Promothod2);
Thread thread4 = new Thread(ptstart);
thread4.Start("我是传进来的参数");//定义一个参数是对象类型的函数
public static void Promothod2(object data) {Console.WriteLine("传进来的参数:" + data);
}

带有参数的委托类(使用箭头函数方法)

Thread thread5 = new Thread((e) => {Console.WriteLine(e);
});
thread5.Start(abc);

Join 阻塞线程

static void Main(string[] args) { //Main是主函数//创建一个线程并执行Thread thread6 = new Thread((e) => {Console.WriteLine(e);Thread.Sleep(6000)});thread6.Start(abc);// Join 阻塞当前依赖的主线程,直到分线程执行完毕thread6.Join();//下面这行代码需要等到上面的线程运行完才会执行Console.WriteLine("这句代码是在主线程中执行的");
}
线程抢占

线程抢占是由操作系统负责的,它决定哪个线程将获得 CPU 的执行时间。

如果两个线程同时对某一个资源进行访问,就可能出现线程抢占的问题。

线程锁

线程锁是一种用于控制多个线程对共享资源进行访问的机制,以防止并发访问时出现数据不一致或错误的情况。使用锁能够确保在某一时刻只有一个线程可以访问共享资源,其他线程需要等待获取锁的释放才能继续执行。

线程锁抢票案例、

static int p = 1;
static readonly object locker = new object(); //当做一个锁
static void Main(string[] args) {Thread thread1 = new Thread(Go);thread1.Name = "张三";thread1.Start();Thread thread2 = new Thread(Go);thread2.Name = "李四";thread2.Start();
}
static void Go() {
//lock 语句获取给定对象的互斥 lock,执行语句块,然后释放 lock。 持有 lock 时,持有 lock 的线程可以再次获取并释放 lock。 阻止任何其他线程获取 lock 并等待释放 lock。 lock 语句可确保在任何时候最多只有一个线程执行其主体。lock (locker) {Console.WriteLine(Thread.CurrentThread.Name + "进来了,此时票数为:" + p + "张。");if (p == 1) {Console.WriteLine(Thread.CurrentThread.Name + "买到了" + p + "张票。");} else {Console.WriteLine(Thread.CurrentThread.Name + "没抢到,继续加油!");}}p--;
}

Tack多线程

Task: 是用于表示可以异步执行的操作的类。它允许你在单独的线程或线程池中执行任务,而不必直接操作线程。

Task特点:

  • 异步执行: Task 允许你执行长时间运行的操作,而不会阻塞主线程,从而提高程序的响应性。
  • 任务调度: Task 可以由系统自动分配到线程池中的线程,也可以使用 TaskScheduler 进行任务调度和控制。
  • 任务链式调用: Task 可以进行任务链式调用,允许一个任务完成后自动开始另一个任务,形成任务流水线。

创建一个简单的Task对象

var task1 = new Task(() => {Console.WriteLine("task分线程任务");
});
//实例化Task之后也需要调用Start才会执行
task1.Start();

创建一个带参数的Task对象

//携带参数,参数放在箭头函数的后面
Task task2 = new Task(e => {Console.WriteLine(e);
}, 123);
task2.Start();

Run 在线程池上运行的指定工作排队,并返回该工作的任务或Task

//带有返回类型,Run适合多线程的操作
//使用Run方法就不需要Start在开启了
Task task = Task.Run(() => {for (int i = 0; i < 10; i++) {Console.WriteLine("task:{0}", (i + 1));Thread.Sleep(500);}
});Task task2 = Task.Run(() => {//Wait 只有等到第一个执行完毕之后才会执行第二个task.Wait();Console.WriteLine("task2开始执行了。");
});//Task.WaitAll(task);//等待所有任务都执行完毕(大家一起执行)
//Task.WaitAny(task);//任意一个任务完成都会向下执行(竞速)//task3.ContinueWith(t => { }); //上一个task完成之后会自动启动下一个task,实现task的延续
Task task5 = Task.Run(() => {Console.WriteLine("5555");
});task5.ContinueWith(t => {Task.Run(() => {Console.WriteLine("test");});
});

线程池

线程池(ThreadPool):线程和线程池都是进行多线程操作的。线程池可以用来理解为是保存线程的一个容器。

 //WaitCallback 是一个委托类型,它用于表示一个在线程池中执行的方法。WaitCallback waitCallback = new WaitCallback(ProgramMothod);//创建线程池:在程序创建线程来执行任务的时候,如果交给了线程池操作,那么线程即使执行完毕了也不会被销毁,而是被挂起了,等待下一个任务被激活。//当线程池里面的资源不够用的时候,会实例化一个新线程,来执行。默认线程池里面的线程是会反复利用的。//标准写法ThreadPool.QueueUserWorkItem(waitCallback);//简写1(箭头函数)
WaitCallback w2 = arg => Console.WriteLine("do something2");
ThreadPool.QueueUserWorkItem(w2);//简写2(箭头函数)
ThreadPool.QueueUserWorkItem(e => {Console.WriteLine("dosimething3");
});//传参的写法(参入一个对象作为参数)
//第一个参数表示委托,第二个参数是参数对象,用于给委托传递数据
ThreadPool.QueueUserWorkItem((e) => {People p = e as People; //这里使用了 as 关键字转义类型Console.WriteLine(p.Id);
}, new People() { Id = 100 });//定义一个类型为object类型的方法
public static void ProgramMothod(object a) {Console.WriteLine("do something");
}//定义一个类
public class People {public int Id;
}
线程阻塞:线程在某个操作或条件下停止执行,直到满足特定条件后再继续执行。

ManualResetEvent 多任务通信,用来控制多个线程之间的执行顺序以及时间

ManualResetEvent和线程池(ThreadPool)配合使用

ManualResetEvent mreset = new ManualResetEvent(false);
// ManualResetEvent和线程池(ThreadPool)配合使用
ThreadPool.QueueUserWorkItem(m => {Thread.Sleep(2000);Console.WriteLine("准备干一些工作");mreset.Set(); // Set 发送命令,如果有mreset.WaitOne方法在,那么收到Set命令之后,后续的代码才会执行
});
// WaitOne 阻塞线程
//上面执行完才会执行下面的
mreset.WaitOne(); 
Console.WriteLine("waitOne收到信号才会打印");

ManualResetEvent和Task配合使用

//下面将用于个打印奇数和偶数的案例演示和Task配合使用的情况
ManualResetEvent je = new ManualResetEvent(false);
Task task = new Task(e => {//打印所有的奇数Js(e);je.Set(); //发送命令
}, 10);ManualResetEvent oe = new ManualResetEvent(false);
Task task2 = new Task(e => {//打印所有的偶数Os(e);oe.Set();//发送命令
}, 10);
task.Start();
task2.Start();
oe.WaitOne();
je.WaitOne();Console.WriteLine("奇数和偶数都打印完毕了");//定义一个打印奇数的方法
public static void Js(object e) {int x = Convert.ToInt32(e);for (int i = 1; i <= x; i += 2) {Console.WriteLine("奇数:" + i);Thread.Sleep(500);}
}
//定义一个打印偶数的方法
public static void Os(object e) {int x = Convert.ToInt32(e);for (int i = 0; i <= x; i += 2) {Console.WriteLine("偶数:" + i);Thread.Sleep(500);}
}

ThreadPool、Thread、Task三者 都是用于多线程编程的类或机制

三者的区别

  • ThreadPool 更适合处理较小的异步操作,而不需要手动创建和管理线程。
  • Thread 提供了对线程的直接控制,但需要手动管理线程的生命周期。
  • Task 是一个高级抽象,结合 async/await 更方便编写和管理异步代码,它可以利用线程池或后台线程来执行任务。

使用工厂模式创建Task

//工厂模式创建Task
var task3 = Task.Factory.StartNew(() => {Console.WriteLine("这是使用Factory工厂模式创建的线程1");
});
Task.Factory.StartNew(() => {Console.WriteLine("这是使用Factory工厂模式创建的线程2");
});//带有返回类型的Task
Task<int> task4 = Task.Factory.StartNew<int>(() => {Console.WriteLine("这是使用Factory工厂模式创建的线程3");return 100;
});
//使用 Result 方法获取返回的值
Console.WriteLine(task4.Result);//100//带有返回类型和参数:数字100是匿名函数的参数,return 200 表示匿名函数的返回值
Task.Factory.StartNew<int>(e => {Console.WriteLine("这是使用Factory工厂模式创建的线程4");return 200;
}, 100);

相关文章:

C#基础——线程(线程池、线程锁、线程抢占、多线程)

线程 进程&#xff08;Process&#xff09;是由操作系统分配资源并执行的一个独立的程序实&#xff0c;属于Windows的概念&#xff0c;进程结束就表示程序关闭了。 线程&#xff08;Thread&#xff09;是程序中执行的最小单位。一个线程代表了一个独立的执行流&#xff0c;可…...

C# WPF上位机开发(QT vs WPF)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 最近经常收到朋友们的私信&#xff0c;他们对C# WPF开发很感兴趣&#xff0c;但是呢&#xff0c;正当准备学习的时候&#xff0c;又有人告诉他们应…...

2-高可用-负载均衡、反向代理

负载均衡、反向代理 upstream server即上游服务器&#xff0c;指Nginx负载均衡到的处理业务的服务器&#xff0c;也可以称之为real server,即真实处理业务的服务器。 对于负载均衡我们要关心的几个方面如下&#xff1a; 上游服务器配置&#xff1a;使用upstream server配置上…...

STM32 使用ARM仿真器设置

STM32单片机程序下载到单片机芯片中有两种方式&#xff0c;①编译生成HEX&#xff0c;使用程序烧录软件刷到单片机芯片里。②使用ARM仿真器下载程序。使用ARM仿真器的优势是&#xff0c;在工程编译没问题直接在Keil软件里就可以将程序下载到单片机里&#xff0c;并且程序可以在…...

【Java】spring

一、spring spring是一个很大的生态圈&#xff0c;里面有很多技术。 其中最基础的是spring framework&#xff0c;主要的技术 是springboot以及springcloud。 1、spring framework spring framework是spring生态圈中最基础的项目&#xff0c;是其他项目的基础。 1.1、核心…...

C语言中关于操作符的理解

本篇文章只会列出大家在生活中经常使用的操作符 算术操作符 在算数操作符中常用的有&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;% &#xff0c;我们重点讲一讲 / (除) 和 % (模) " / "运算 #include <stdio.h>int main() {int a5/2;fl…...

Flutter本地化(国际化)之App名称

文章目录 Android国际化IOS国际化 Flutter开发的App&#xff0c;如果名称想要跟随着系统的语言自动改变&#xff0c;则必须同时配置Android和IOS原生。 Android国际化 打开android\app\src\main\res\values 创建strings.xml 在values上右键&#xff0c;选择New>Values Res…...

Redis哨兵源码分析

在Redis server启动过程中&#xff0c;实现了实例化和初始化 1、哨兵实例化过程&#xff0c;采用redis sentinel指令实例化还是redis server下的参数实例化--sentinel。 // 检查服务器是否以 Sentinel 模式启动 server.sentinel_mode checkForSentinelMode(argc,argv);/* Re…...

安装Neo4j

jdk1.8对应的neo4j的版本是3.5 自行下载3.5版本的zip文件 地址 解压添加环境变量 变量名&#xff1a;NEO4J_HOME 变量值&#xff1a;D:\neo4j-community-3.5.0 &#xff08;你自己的地址&#xff09; PATH添加&#xff1a; %NEO4J_HOME%\bin (如果是挨着的注意前后英…...

华为鸿蒙开发适合哪些人学习?

随着鸿蒙系统的崛起&#xff0c;越来越多的人开始关注鸿蒙开发&#xff0c;并希望成为鸿蒙开发者。然而&#xff0c;鸿蒙开发并不适合所有人&#xff0c;那么哪些人最适合学习鸿蒙开发呢&#xff1f;本文将为您总结鸿蒙开发适合的人群。 一、具备编程基础的人 学习鸿蒙开发需要…...

深信服技术认证“SCSA-S”划重点:命令执行漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…...

Flink系列之:Savepoints

Flink系列之&#xff1a;Savepoints 一、Savepoints二、分配算子ID三、Savepoint 状态四、算子五、触发Savepoint六、Savepoint 格式七、触发 Savepoint八、使用 YARN 触发 Savepoint九、使用 Savepoint 停止作业十、从 Savepoint 恢复十一、跳过无法映射的状态恢复十二、Resto…...

使用宝塔面板部署前端项目到服务器

目录 文章目录 前言 一、第一步&#xff1a;创建文件夹 二、第二步&#xff1a;部署前端项目 三、第三步&#xff1a;打开防火墙 文章目录 前言第一步&#xff1a;创建文件夹第二步&#xff1a;部署前端项目第三步&#xff1a;打开防火墙总结 前言 在此之前&#xff0c;我…...

Enge问题解决教程

目录 解决问题的一般步骤&#xff1a; 针对"Enge问题"的具体建议&#xff1a; 以下是一些普遍适用的解决问题的方法&#xff1a; 以下是一些更深入的Enge浏览器问题和解决办法&#xff1a; 浏览器性能问题&#xff1a; 浏览器插件与网站冲突&#xff1a; 浏览…...

使用yarn安装electron时手动选择版本

访问1Password或者其他可以提供随机字符的网站&#xff0c;获取随机密码运行安装命令 操作要点&#xff0c;必须触发Couldnt find any versions for "electron" that matches "*"才算成功 将复制的随机密码粘贴到后面 例如&#xff1a;yarn add --dev elec…...

AIGC:阿里开源大模型通义千问部署与实战

1 引言 通义千问-7B&#xff08;Qwen-7B&#xff09;是阿里云研发的通义千问大模型系列的70亿参数规模的模型。Qwen-7B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样&#xff0c;覆盖广泛&#xff0c;包括大量网络文本、专业书籍…...

Java小案例-Java实现人事管理系统

前言 《人事管理系统》该项目采用技术jsp、Struts2、Mybatis、dwr、tomcat服务器、mysql数据库 开发工具eclipse/idea。 【项目使用技术】 Struts2Mybatisdwrjqueryjscss等技术 前端使用技术&#xff1a;JSP, dwr、jquery、js、css等 后端使用技术&#xff1a;Struts2Myba…...

Win系统修改Nginx配置结合内网穿透实现远程访问多个Web站点

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…...

如何使用 NFTScan NFT API 在 Base 网络上开发 Web3 应用

Base 是 Coinbase 使用 OP Stack 开发的最新以太坊第 2 层&#xff08;L2&#xff09;网络&#xff0c;用于解决以太坊等主要区块链面临的可扩展性和成本挑战。Coinbase 将其描述为“安全、低成本、对开发人员友好的以太坊 L2&#xff0c;旨在将下一个 10 亿用户带入 Web3”。B…...

【Chrome】ERR_SSL_PROTOCOL_ERROR问题

文章目录 前言一、下载二、使用步骤总结 前言 Edge升级最新版后&#xff0c;有的https访问不了&#xff0c;报如下错误 发现新版Chrome以及Chromium内核访问nginx ssl时报错&#xff0c;顺着这个思路接着查看到大佬的结论&#xff1a;服务器nginx使用的openssl版本过低&#…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...