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#基础——线程(线程池、线程锁、线程抢占、多线程)
线程 进程(Process)是由操作系统分配资源并执行的一个独立的程序实,属于Windows的概念,进程结束就表示程序关闭了。 线程(Thread)是程序中执行的最小单位。一个线程代表了一个独立的执行流,可…...
C# WPF上位机开发(QT vs WPF)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 最近经常收到朋友们的私信,他们对C# WPF开发很感兴趣,但是呢,正当准备学习的时候,又有人告诉他们应…...
2-高可用-负载均衡、反向代理
负载均衡、反向代理 upstream server即上游服务器,指Nginx负载均衡到的处理业务的服务器,也可以称之为real server,即真实处理业务的服务器。 对于负载均衡我们要关心的几个方面如下: 上游服务器配置:使用upstream server配置上…...
STM32 使用ARM仿真器设置
STM32单片机程序下载到单片机芯片中有两种方式,①编译生成HEX,使用程序烧录软件刷到单片机芯片里。②使用ARM仿真器下载程序。使用ARM仿真器的优势是,在工程编译没问题直接在Keil软件里就可以将程序下载到单片机里,并且程序可以在…...
【Java】spring
一、spring spring是一个很大的生态圈,里面有很多技术。 其中最基础的是spring framework,主要的技术 是springboot以及springcloud。 1、spring framework spring framework是spring生态圈中最基础的项目,是其他项目的基础。 1.1、核心…...
C语言中关于操作符的理解
本篇文章只会列出大家在生活中经常使用的操作符 算术操作符 在算数操作符中常用的有,,-,*,/,% ,我们重点讲一讲 / (除) 和 % (模) " / "运算 #include <stdio.h>int main() {int a5/2;fl…...
Flutter本地化(国际化)之App名称
文章目录 Android国际化IOS国际化 Flutter开发的App,如果名称想要跟随着系统的语言自动改变,则必须同时配置Android和IOS原生。 Android国际化 打开android\app\src\main\res\values 创建strings.xml 在values上右键,选择New>Values Res…...
Redis哨兵源码分析
在Redis server启动过程中,实现了实例化和初始化 1、哨兵实例化过程,采用redis sentinel指令实例化还是redis server下的参数实例化--sentinel。 // 检查服务器是否以 Sentinel 模式启动 server.sentinel_mode checkForSentinelMode(argc,argv);/* Re…...
安装Neo4j
jdk1.8对应的neo4j的版本是3.5 自行下载3.5版本的zip文件 地址 解压添加环境变量 变量名:NEO4J_HOME 变量值:D:\neo4j-community-3.5.0 (你自己的地址) PATH添加: %NEO4J_HOME%\bin (如果是挨着的注意前后英…...
华为鸿蒙开发适合哪些人学习?
随着鸿蒙系统的崛起,越来越多的人开始关注鸿蒙开发,并希望成为鸿蒙开发者。然而,鸿蒙开发并不适合所有人,那么哪些人最适合学习鸿蒙开发呢?本文将为您总结鸿蒙开发适合的人群。 一、具备编程基础的人 学习鸿蒙开发需要…...
深信服技术认证“SCSA-S”划重点:命令执行漏洞
为帮助大家更加系统化地学习网络安全知识,以及更高效地通过深信服安全服务认证工程师考核,深信服特别推出“SCSA-S认证备考秘笈”共十期内容,“考试重点”内容框架,帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…...
Flink系列之:Savepoints
Flink系列之:Savepoints 一、Savepoints二、分配算子ID三、Savepoint 状态四、算子五、触发Savepoint六、Savepoint 格式七、触发 Savepoint八、使用 YARN 触发 Savepoint九、使用 Savepoint 停止作业十、从 Savepoint 恢复十一、跳过无法映射的状态恢复十二、Resto…...
使用宝塔面板部署前端项目到服务器
目录 文章目录 前言 一、第一步:创建文件夹 二、第二步:部署前端项目 三、第三步:打开防火墙 文章目录 前言第一步:创建文件夹第二步:部署前端项目第三步:打开防火墙总结 前言 在此之前,我…...
Enge问题解决教程
目录 解决问题的一般步骤: 针对"Enge问题"的具体建议: 以下是一些普遍适用的解决问题的方法: 以下是一些更深入的Enge浏览器问题和解决办法: 浏览器性能问题: 浏览器插件与网站冲突: 浏览…...
使用yarn安装electron时手动选择版本
访问1Password或者其他可以提供随机字符的网站,获取随机密码运行安装命令 操作要点,必须触发Couldnt find any versions for "electron" that matches "*"才算成功 将复制的随机密码粘贴到后面 例如:yarn add --dev elec…...
AIGC:阿里开源大模型通义千问部署与实战
1 引言 通义千问-7B(Qwen-7B)是阿里云研发的通义千问大模型系列的70亿参数规模的模型。Qwen-7B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样,覆盖广泛,包括大量网络文本、专业书籍…...
Java小案例-Java实现人事管理系统
前言 《人事管理系统》该项目采用技术jsp、Struts2、Mybatis、dwr、tomcat服务器、mysql数据库 开发工具eclipse/idea。 【项目使用技术】 Struts2Mybatisdwrjqueryjscss等技术 前端使用技术:JSP, dwr、jquery、js、css等 后端使用技术: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 层(L2)网络,用于解决以太坊等主要区块链面临的可扩展性和成本挑战。Coinbase 将其描述为“安全、低成本、对开发人员友好的以太坊 L2,旨在将下一个 10 亿用户带入 Web3”。B…...
【Chrome】ERR_SSL_PROTOCOL_ERROR问题
文章目录 前言一、下载二、使用步骤总结 前言 Edge升级最新版后,有的https访问不了,报如下错误 发现新版Chrome以及Chromium内核访问nginx ssl时报错,顺着这个思路接着查看到大佬的结论:服务器nginx使用的openssl版本过低&#…...
Codeforces Round 916 (Div. 3)(E:贪心 F贪心dfs G tarjan+topsort +线段树优化建图)
A:直接暴力统计每个字符的次数是否达标即可 #include<bits/stdc.h> using namespace std; const int N 3e510,mod998244353; #define int long long typedef long long LL; typedef pair<int, int> PII; typedef unsigned long long ULL;const long l…...
eNSP错误40,原因三:windows10自带虚拟化软件Hyper-V
问题描述 Hyper-V软件与VirtualBox不兼容,一旦开启Hyper-V的话eNSP的路由器就会无法开启,显示ERROR 40 原理 大家注意看hypervisor的两种类型: 左边的是开启hypervisor的Type-1,hypervisor在启用的时候,宿主机也相…...
Maven将Jar包打入本地仓库
Maven将Jar包打入本地仓库 Maven将Jar包打入本地仓库嘚吧嘚下载Maven配置Maven新建MAVEN_HOME编辑Path验证Maven配置 Jar包打入Maven仓库 Maven将Jar包打入本地仓库 嘚吧嘚 最近项目用到一个Jar包,不能从远程仓库拉取,只有一个Jar包,所以需…...
如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 1
本系列将分成三个部分,您将学习如何使用 Helm 在 Kubernetes 上集成 Prometheus 和 Grafana,以及如何在 Grafana 上创建一个简单的控制面板。Prometheus 和 Grafana 是 Kubernetes 最受欢迎的两种开源监控工具。学习如何使用 Helm 集成这两个工具&#x…...
Observability:捕获 Elastic Agent 和 Elasticsearch 之间的延迟
在现代 IT 基础设施的动态环境中,高效的数据收集和分析至关重要。 Elastic Agent 是 Elastic Stack 的关键组件,通过促进将数据无缝摄取到 Elasticsearch 中,在此过程中发挥着至关重要的作用。 然而,显着影响此过程整体有效性的关…...
Ubuntu 常用命令之 less 命令用法介绍
📑Linux/Ubuntu 常用命令归类整理 less命令是一个在Unix和Unix-like系统中用于查看文件内容的命令行工具。与more命令相比,less命令提供了更多的功能和灵活性,例如向前和向后滚动查看文件,搜索文本,查看长行等。 les…...
探索Node.js包管理器npm:介绍与使用指南
引言: 在现代软件开发中,包管理器已经成为了不可或缺的工具。它们简化了软件的安装、升级和管理过程,使得开发者能够更加高效地构建项目。而作为Node.js的官方包管理器,npm(Node Package Manager)无疑是最受…...
探讨APP自动化测试工具的重要性
随着移动应用市场的蓬勃发展,企业对于保证其移动应用质量和用户体验的需求日益迫切。在这一背景下,APP自动化测试工具正变得越来越重要,成为企业成功的关键组成部分。本文将探讨APP自动化测试工具对企业的重要性,并为您解析其在提…...
el-date-picker日期时间插件只允许选择年月日小时并做可选择范围限制(精确到小时的范围)
一、首先明确下这个需求 1、要求只能选择年月日时,不要分钟和秒 2、根据后台返回的开始时间和天数设置可选择的开始时间和结束时间范围(包含小时)比如后台返回的开始时间是2023-12-20 13:24:30,天数365天,那么我们需要限制当前可选日期为2023-12-20 14时(不能选小于13:2…...
在MongoDB中使用数组字段和子文档字段进行索引
本文主要介绍在MongoDB使用数组字段和子文档字段进行索引。 目录 MongoDB的高级索引一、索引数组字段二、索引子文档字段 MongoDB的高级索引 MongoDB是一个面向文档的NoSQL数据库,它提供了丰富的索引功能来加快查询性能。除了常规的单字段索引之外,Mong…...
wordpress123页/潍坊住房公积金管理中心
做了那么久的动态网页,特别是类似于文章或者是新闻系统,都是按照很传统的方法来做的。但是看到越来越多的网站都使用生成静态网页的方法,于是我也打算使用这个方法实践一下。希望对一些有这方面的需要的朋友提供点帮助。 本人使用IIS6.0asp.n…...
网站改版iis301跳转如何做/seo关键词优化要多少钱
2020考研复试备考第9周总结 又一个星期过去了。复试的消息仍然没有传出来。感觉这个星期挺累的,但好像也没做多少事情。今天参加了优秀毕业生的答辩,自己的确没有什么突出的点,老师连提问都省了,就直接讲了1分多钟,结…...
网站制作设计/google下载
RabbitMQ: 优点:轻量,迅捷,容易部署和使用,拥有灵活的路由配置 缺点:性能和吞吐量较差,不易进行二次开发 RocketMQ: 优点:性能好,稳定可靠,有活…...
上海做设计公司网站/微信推广平台
Nginx的简介 Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发࿰…...
黑科技软件网站/推广公司是做什么的
一. 静态库的生成 1. 测试目录: lib 2. 源码文件名: mywindow.h, mywindow.cpp, 类MyWindow继承于QPushButton, 并将文字设置为"Im in class MyWindow"; 3. 编写项目文件: mywindow.pro 注意两点: TEMPLATE lib CONFIG staticlib …...
设计师培训机构有哪些/开源seo软件
译自Matthew的《A Good Part-of-Speech Tagger in about 200 Lines of Python》,本文用最精简的代码演示了如何写一个基于感知机的高性能词性标注器。以下是正文:自然语言处理的最新技术大部分都停留在学术界,但学术界往往非常谨慎、不愿意把…...