Unity 线程相关知识

server/2024/11/14 20:02:36/

线程

线程介绍

通过线程执行函数和直接在主函数中调用函数的区别是:通过直接调用函数时会按照语句顺序逐句执行,必定会完成上一句后再执行下一句,而通过线程执行的函数会从调用开始与主函数同步执行

调用线程的方式

调用无参数函数线程的方法:

    void Start(){Thread thread = new Thread(SendThread);thread.Start();}void SendThread(){Debug.Log("调用线程");}

调用有参数函数线程时,使用lambda表达式在创建线程时传入函数的参数

    void Start(){Thread t1 = new Thread(() => { SendThread("一", 100); });Thread t2 = new Thread(() => { SendThread("二", 50); });Thread t3 = new Thread(() => { SendThread("三", 25); });t1.Start();t2.Start();t3.Start();}void SendThread(string name,int i){while (i >= 0){Debug.Log(name + "执行剩余" + i--);}}

线程休眠 

调用Thread.Sleep(int)方法

public static void Sleep(int millisecondsTimeout);

传入的参数为毫秒,1000毫秒等于一秒

            //线程休眠一秒Thread.Sleep(1000);

线程池

线程池介绍

在调用线程的时候,会先创建线程,然后再线程结束后销毁线程,如果频繁对线程进行创建和销毁会极大的损耗计算机的性能,所以在频繁创建逻辑简短的线程的时候,最好使用线程池

调用线程池的方法

能够在线程池中调用的线程与直接创建线程不同的地方在于:线程池中调用的线程的参数必须限定格式,线程池能调用的线程必须只能拥有一个object类型的参数

通过ThreadPool.QueueUserWorkItem方法使用线程池调用线程

public static bool QueueUserWorkItem(WaitCallback callBack, object state);

第一个参数为想要执行线程的函数,函数必须只有一个object参数

第二个参数为传递给线程函数的参数

与直接创建线程不同的是,线程池中的线程不需要Start,添加线程时自动开始执行

示例代码:

    void Start(){ThreadPool.QueueUserWorkItem(SendThreadPool,10);ThreadPool.QueueUserWorkItem(SendThreadPool,10.01);ThreadPool.QueueUserWorkItem(SendThreadPool,"十");}void SendThreadPool(object obj){for (int i = 0; i < 10; i++){Debug.Log(obj.ToString() + "剩余" + i);}}

设置线程池中最多同时运行线程数量

public static bool SetMaxThreads(int workerThreads, int completionPortThreads);

第一个参数为线程池中辅助线程的最大数目,与第二个参数相同即可

第二个参数为线程池中异步 I/O 线程的最大数目,与第一个参数相同即可

示例代码:

ThreadPool.SetMaxThreads(10,10);

线程同步

线程同步介绍

线程的运行是不规律的,结果不可控的,可能会涉及到一个线程中使用一个值之前这个值被另一个线程改变了,从而导致出现未知错误,这种情况下就需要控制线程执行的顺序,规避问题

Mutex 互斥锁

通过定义Mutex类型变量互斥锁,来达到同步效果,可以在执行重要逻辑前先对Mutex类型变量进行锁定,然后第二个线程尝试执行锁定Mutex变量时如果Mutex变量已被锁定,则第二个线程将会暂停运行,直到第一个锁定Mutex变量的线程将Mutex变量解锁,第二个线程才会继续锁定Mutex变量并开始工作,直到再次解锁Mutex变量为止

示例代码:

    int number;Mutex mutex = new Mutex();void Start(){Thread t1 = new Thread(() => { SendThread("一",10); });Thread t2 = new Thread(() => { SendThread("二",8); });Thread t3 = new Thread(() => { SendThread("三",5); });t1.Start();t2.Start();t3.Start();}void SendThread(string name,int i){for (; i > 0; i--){mutex.WaitOne();for (int j = 0; j < i; j++){number += i;Debug.Log(name + "给数值增加了" + i + "现在的数值为" + number);}mutex.ReleaseMutex();}}

Lock 变量锁

通过Lock关键字来达到同步效果,和Mutex使用相似,执行重要逻辑前,锁住任意变量,将逻辑写入lock语句内,其余线程执行lock发现lock中的变量被锁住将会等待,等待前一线程的lock执行完毕释放lock关键字中的变量后再执行(lock锁住的变量可以和需要保护的变量毫无关系,可以锁住任意变量达到效果,但注意变量类型必须是引用类型,值类型变量无法使用lock关键字)

示例代码:

    int number;object obj = new object();void Start(){Thread t1 = new Thread(() => { SendThread("一",10); });Thread t2 = new Thread(() => { SendThread("二",8); });Thread t3 = new Thread(() => { SendThread("三",5); });t1.Start();t2.Start();t3.Start();}void SendThread(string name,int i){for (; i > 0; i--){lock (obj) {for (int j = 0; j < i; j++){number += i;Debug.Log(name + "给数值增加了" + i + "现在的数值为" + number);}}Thread.Sleep(100);}}

Semaphore 多通道锁

Semaphore与Mutex不同的地方在于,Mutex一次只能固定允许一个线程访问,而Semaphore可以设置最多同时访问的最大数量,如果给Semaphore的最大访问值设置为2,同时有10个线程需要访问时,只有前2个线程能够成功访问,而剩余的8个线程则需要等待,等前两个线程执行完后,再同时让第3和第4个访问通道的线程执行,剩余的6个线程等待,直到执行完毕

示例代码:

    int number;Semaphore semaphore = new Semaphore(2,2);void Start(){Thread t1 = new Thread(() => { SendThread("一", 10); });Thread t2 = new Thread(() => { SendThread("二", 8); });Thread t3 = new Thread(() => { SendThread("三", 5); });t1.Start();t2.Start();t3.Start();}void SendThread(string name, int i){for (; i > 0; i--){semaphore.WaitOne();for (int j = 0; j < i; j++){number += i;Debug.Log(name + "给数值增加了" + i + "现在的数值为" + number);}semaphore.Release();}}

http://www.ppmy.cn/server/8076.html

相关文章

几道练习题八

第 1 题 【 问答题 】 • 多项式相加 我们经常遇到两多项式相加的情况&#xff0c; 在这里&#xff0c; 我们就需要用程序来模拟实现把两个多项式相加到一起。 首先&#xff0c; 我们会有两个多项式&#xff0c;每个多项式是独立的一行&#xff0c; 每个多项式由系数、 幂数这样…

计算机网络中的一些基本概念

ip地址&#xff1a;IP地址是ip协议提供的一种统一的地址格式&#xff0c;它为互联网上的每一个网络和每一台主机分配一个逻辑地址&#xff0c;以此来屏蔽物理地址的差异。是用来区分主机的。 端口号&#xff1a;每个应用程序对应一个端口号&#xff0c;通过类似门牌号的端口号…

【PCL】教程correspondence_grouping对点云模型和点云场景进行特征提取,匹配,以及聚类找到模型与场景的匹配...

基于对应分组的 3D 对象识别 本教程旨在解释如何使用 pcl_recognition 模块执行基于对应分组的 3D 对象识别。具体来说&#xff0c;它解释了如何使用对应分组算法将 3D 描述符匹配阶段后的点对点对应集聚合到当前场景中的模型实例中。对于每个聚类&#xff0c;表示场景中的可能…

python 又一个点运算符操作的字典库:Munch

munch 库 又一个将字典&#xff08;dict&#xff09;变成类似对象&#xff08;object&#xff09;的库。这意味着你可以使用点符号&#xff08;.&#xff09;而不是方括号&#xff08;[]&#xff09;来访问字典的键。这使得代码更易读&#xff0c;尤其是在处理嵌套字典时。 相…

【Hadoop】- YARN架构[7]

前言 Yarn架构是一个用于管理和调度Hadoop集群资源的系统。它是Hadoop生态系统的一部分&#xff0c;主要用于解决Hadoop中的资源管理问题。 通过使用Yarn架构&#xff0c;Hadoop集群中的不同应用程序可以共享集群资源&#xff0c;并根据需要动态分配和回收资源。这种灵活的资…

CX5120-0125倍福CPU模块维修PLC控制器CX5120全系列主机电脑深圳捷达工控维修

工业计算机服务与维修 为任何品牌的工业计算机、显示器、人机界面 (HMI) 和面板计算设备提供服务、维修和改造。您可以信赖我们延长生命周期&#xff0c;包括不再投放市场的产品。 工业计算机维修与保养 您的工业计算机专家 工业计算机维修服务 深圳捷达工控维修深知做好工业…

【MySQL】脏读,幻读,不可重复读

脏读、幻读、不可重复读 一、脏读 二、幻读 三、不可重复读 四、脏读、幻读、不可重复读的区别 一、脏读 脏读主要发生在隔离级别很低的事务之间&#xff0c;就比如隔离级别设为Read Uncommitted,也就是读为提交。当我们有多个数据库并发的访问一张表的时候&#xff0c;就…

前后端交互概念

前后端交互概念 1前后端分离开发概念2搭建后端环境2.1配置文件commomcommon-utilservice-utilmodelservice gitee使用 1前后端分离开发概念 前段&#xff1a;运用html、css、js和现成库&#xff0c;对数据作展示。 后端&#xff1a;运用Java和Java框架&#xff0c;提供数据或操…