协程

我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了。我们希望我们只要一启动加载的命令,回来的时候主线程能够继续进行下去。

我们可以启动一个协程去下载,主进程依然在运行。有点类似多线程,不同的是,实际上它还是在一个线程里面,所以我们是在主线程中开启一段逻辑来进行处理,来协同当前程序的执行,还是在主线程里面。

1:在主进程中开启另外一段逻辑处理,来协同当前程序的执行,但与多线程不同都是在主线程里面执行的,而且原来的进程依然进行下去,

2:通过StartCoroutine方法来启动一个协程,StartCoroutine是MonoBehaviour的一个方法,该方法可以启动一个协程,每个协程都有一个入口函数,协程必须要是一个IEnumerator 作为返回值的方法(入口函数);

3:协同程序可以使用yield 关键字来中断协同程序;

4:协程也可以启动一个协程;

5:WaitForSeconds(): 等待多长时间后中断协程;

协程实例

1.创建Unity项目和文件目录,保存场景

2.创建一个空节点game,再创建一个脚本game挂载在gamej节点下

 打开game脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class game : MonoBehaviour { private int level=;
// Use this for initialization
void Start () {
//启动一个协程,必须是继承自MonoBehaviour才能使用
this.StartCoroutine(this.con_entry()); //主线程依然在执行
//...
} //协程和主线程是在同一个线程里面的,不会有什么线程切换
//协程的入口函数
IEnumerator con_entry(){
//协程的代码
Debug.Log("con_entry run!!");
Debug.Log("level:" + this.level);//也能够拿到this的变量
this.StartCoroutine(this.con_other());//再开启一个协程con_other
//end //使用yield中断协程程序,就是让它停下来
yield return null; //协程结束以后的代码,比如去网上捞一个什么东西,下载图片之类的,捞完之后的操作
//end
} IEnumerator con_other()
{
Debug.Log("con_other");
this.StartCoroutine(this.con_entry_params());//再开启一个协程con_entry_params,且传递参数 yield return null;
} IEnumerator con_entry_params(int a)
{
Debug.Log("con_entry_params: " + a); yield return new WaitForSeconds();//设置3秒中之后才中断协程 Debug.Log("after WaitForSeconds send");// 处理协程结束的逻辑
} // Update is called once per frame
void Update () { }
}

3.运行结果

多线程

我们的操作系统是多任务操作系统,实际上只有一个cpu是怎样做到多任务的呢?就是通过线程切换来完成的,每个任务可以看成是一个进程或者线程,多任务多线程就是让cpu在线程里面不断地切换,如果切换的频率足够快,人们就会认为多个任务是同时在执行的。

例子:一边编辑文本,一边播MP3,播MP3也就是解码一段3秒钟的音乐,只需要消耗CPU0.01秒,也就是说剩下的2.99秒CPU都是空闲的,所以才提出多线程的解决方案,充分利用CPU资源。

游戏一般都是有一个主线程,是处理游戏的主要事情,但是有些事情我们不希望在主线程里面处理,

比如有一项工作特别耗时,下载一个资源文件,如果把它放在主线程里面等待下载完成的那段时间就卡住了,游戏就卡住了,要等10分钟下载好后主线程才会恢复,这是无法忍受的。

于是我们的做法就是开启另外一个线程,然后再去下载,下载过程中通知主线程当前下载的量,主线程继续执行并更新下载的数据。

多线程的好处是:1.现在的手机电脑的CPU都是多个核的,每个核是可以独立调度一个线程的,本来游戏只在一个核上运行,如果有了一个复杂的计算,把它放在另外一个线程里面,

         如果是运行在双核上面,那就有两个核来运行游戏,一个核来跑主线程,一个核来跑复杂的运算,这样子,基本上CPU的利用率就能上来,就能帮助我们快速处理复杂运算,这个叫做多核优化。

        2.不至于卡死主线程,能够让主线程获得一个更好的处理方式和更好的用户体验

        3.CPU有多个核,有几个核就可以调度几个线程,比如双核的就可以一次性调度两个线程主线程在跑,复杂线程也在跑,都不耽误。

1: using System.Thread;

2: 创建一个线程: Thread r = new Thread(callback);  r.start(); 启动运行线程;

3: 线程回掉函数 void run() {}

4: 多个线程访问同一个数据的时候,会发生”冲突”,需要线程安全的方式来访问;

5: 线程锁是在访问公共数据的时候,先去获得这个锁,没有获得锁的线程将会被挂起,指导这个锁被释放。

6: public static Object  o = new Object(); lock(o) {线程安全的执行代码};

7: 线程休眠: Thread.Sleep(单位为ms);

8: 多线程之间要避免死锁;

多线程案例

1.创建Unity项目和文件目录,保存场景

2.创建一个空节点game,再创建一个脚本game挂载在gamej节点下

 打开game脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;//多线程要用到的库,多线程对象所在的名字空间 public class game : MonoBehaviour { // Use this for initialization
void Start () { //创建一个线程t1,关联入口函数
Thread t1 = new Thread(this.thread_run);//不是像协程那样直接运行
t1.Start();//这里才开始执行,开启线程 //再创建一个线程t2
Thread t2 = new Thread(this.thread_run2);
t2.Start(); } //线程t1的入口函数
void thread_run(){
int i = ;
while (i < ){//打印10次
Debug.Log("thread_run");
i++;
Thread.Sleep();//让线程休息3秒钟,有点像定时器,里面参数是毫秒为单位的
}
} //线程t2的入口函数
void thread_run2(){
int i = ;
while (i < ){//打印10次
Debug.Log("thread_run2");
i++;
Thread.Sleep();
}
} // Update is called once per frame
void Update () {
//Debug.Log("zhu xian cheng");//主线程也在运行
}
}

3.运行结果

线程锁

线程锁,两个线程是独立的,假设他们要访问同一个变量,访问公共的资源(全局变量),就需要加锁,才能保证数据访问的安全

两个人都要访问共用的资源,怎样让他们不冲突,如我正在改,你也在改,那到底是改谁的,哪个逻辑是对的。或者我在读,你在改,我读到的到底是你改之前的还是你改之后的,就会有很多不确定性。

所以,当两个线程来访问公共资源的时候,可以采用锁的结构来解决这个问题,就是说你进来之前先拉一下锁,如果你拿到了这个锁的权利,这时候就你进去访问,其他的线程就会挂起等待,等到你把这个锁释放出来,再继续。

线程锁案例

1.创建Unity项目和文件目录,保存场景

2.创建一个空节点game,再创建一个脚本game挂载在gamej节点下

 打开game脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;//多线程要用到的库,多线程对象所在的名字空间 public class game : MonoBehaviour { // 定义一个静态全局的对象,这个就是锁了
public static Object o = new Object(); //定义一个静态变量可以被全局访问
public static int g_a = ; // Use this for initialization
void Start () { //创建一个线程t1,关联入口函数
Thread t1 = new Thread(this.thread_run);//不是像协程那样直接运行
t1.Start();//这里才开始执行,开启线程 //再创建一个线程t2
Thread t2 = new Thread(this.thread_run2);
t2.Start(); } //线程t1的入口函数
void thread_run(){
Debug.Log("thread_run wait for lock...");
lock (o) // 如果没有获得这个锁,那么线程就会挂起等待,只有等他获得了这个锁才会继续往下执行,这个o就是一个锁
{ // 你获取到了这个锁,开始操作
Debug.Log("thread_run get lock");
g_a = ;
Debug.Log("g_a = " + g_a);
Thread.Sleep();//故意让它睡20秒便于观察
Debug.Log("thread_run release lock");
} // 括号结束了以后,你就释放了这个锁,其他的线程就有机会获得这个锁 } //线程t2的入口函数
void thread_run2(){
Debug.Log("thread_run2 wait for lock...");
lock (o) // 如果没有获得这个锁,那么线程就会挂起等待,只有等他获得了这个锁才会继续往下执行,这个o就是一个锁
{ // 你获取到了这个锁,开始操作
Debug.Log("thread_run2 get lock");
g_a = ;
Debug.Log("g_a = " + g_a);
Thread.Sleep();//故意让它睡20秒便于观察
Debug.Log("thread_run2 release lock");
} // 括号结束了以后,你就释放了这个锁,其他的线程就有机会获得这个锁 } // Update is called once per frame
void Update () { }
}

3.运行结果

死锁

死锁,线程A拿了锁A,在等待锁B,线程B拿了锁B,在等待锁A,两个线程彼此都拿了一个锁,我在等你,你在等我,在等待彼此的对方的锁不让步,这就是死锁。

死锁后很麻烦,要重启Unity。

死锁案例

1.创建Unity项目和文件目录,保存场景

2.创建一个空节点game,再创建一个脚本game挂载在gamej节点下

 打开game脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;//多线程要用到的库,多线程对象所在的名字空间 public class game : MonoBehaviour { /*
* 死锁: A线程拿了锁A,在等拿锁B;
* B线程拿了锁B,在等拿锁A;
* 如果说你一个线程同时要获取多个锁的时候,为了比避免死锁,
* 你要按照相同的次序来拿;
*/ //定义两个锁,分别为锁A和锁B
public static Object A = new Object();
public static Object B = new Object(); // Use this for initialization
void Start () { //创建一个线程t1,关联入口函数
Thread t1 = new Thread(this.thread_run);//不是像协程那样直接运行
t1.Start();//这里才开始执行,开启线程 //再创建一个线程t2
Thread t2 = new Thread(this.thread_run2);
t2.Start(); } //线程t1的入口函数
void thread_run(){
lock (A)
{
Thread.Sleep();//先休息3秒钟,保证线程2拿到锁B
Debug.Log("t1 wait for Lock B");
lock (B)
{
Debug.Log("t1 run");
}
Debug.Log("t1 release B");
}
Debug.Log("t1 release A");
} //线程t2的入口函数
void thread_run2(){
//死锁语句
/*lock (B)
{
Thread.Sleep(3000);//先休息3秒钟,保证线程1拿到锁A
Debug.Log("wait for Lock A");
lock (A)
{
Debug.Log("run");
}
Debug.Log("release A");
}
Debug.Log("release B");
*/ //解决死锁的方法
lock (A)
{
Thread.Sleep();
Debug.Log("t2 wait for Lock B");
lock (B)
{
Debug.Log("t2 run");
}
Debug.Log("t2 release B");
}
Debug.Log("t2 release A");
} // Update is called once per frame
void Update () { }
}

3.运行结果

死锁

死锁解决

WWW

Unity中用来处理HTTP协议相关的,有HTTPget和HTTPpost,WWW就是HTTP封装的一个对象

1: WWW w = new WWW(url);
2: WWW(url)会在后台下载url数据;
3: yeild return w来在协程里等待下载完成;
4: 完成后可以继续处理;

5.还可以获取网页其他的内容,数据,表单,图片等等,可以点击WWW类点F12查看。

WWW案例

1.创建Unity项目和文件目录,保存场景

2.创建一个空节点game,再创建一个脚本game挂载在gamej节点下

 打开game脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;//多线程要用到的库,多线程对象所在的名字空间 public class game : MonoBehaviour { // Use this for initialization
void Start () { //创建一个线程t1,关联入口函数
Thread t1 = new Thread(this.thread_run);//不是像协程那样直接运行
t1.Start();//这里才开始执行,开启线程 //再创建一个线程t2
Thread t2 = new Thread(this.thread_run2);
t2.Start(); // 启动一个协程去加载网络数据---->捞百度网页
this.StartCoroutine(this.http_get_baidu());
Debug.Log("do other");//可以马上做其他的事情,抓百度网站的事情交给协程去做
} IEnumerator http_get_baidu()
{
// 完成unity http请求和协议;
WWW w = new WWW("www.baidu.com");
// 网络需要抓取时间,在后台抓取网络数据,一段时间以后,才能完整的抓完整个数据;
yield return w; // 抓取完成网络数据
Debug.Log(w.text);
// end
} //线程t1的入口函数
void thread_run(){ } //线程t2的入口函数
void thread_run2(){ } // Update is called once per frame
void Update () { }
}

3.运行结果

关于Unity中协程、多线程、线程锁、www网络类的使用的更多相关文章

  1. unity3D中协程和线程混合

    这是我google unity3D一个问题偶然发现的在stackflow上非常有趣的帖子: 大意是 要在unity3D上从server下载一个zip,并解压到持久化地址.并将其载入到内存中.以下展示了 ...

  2. day37协程与线程套接字通讯

    协程与线程套接字通讯基于多线程实现套接字服务端支持并发,服务端 from socket import * from threading import Thread def comunicate(con ...

  3. python中协程实现的本质以及两个封装协程模块greenle、gevent

    协程 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源). 为啥说它是一个执行单元,因为 ...

  4. Lua 协程和线程区别

    协程就是协程,不是线程. CPU执行单位是线程,不是什么协程. 协程,是同步执行,不是并行,只是切了一个上下文了,为你保存原来的上下文而已. 切到第二个协程时,原来的协程处于挂起状态. 这个特指lua ...

  5. Go语言协程并发---互斥锁sync.Mutex

    package main import ( "fmt" "sync" "time" ) /* mt.Lock() 抢锁 一次只能被一个协程锁 ...

  6. Unity 协程与线程

    协程是不同步的 协程 不是 线程,协同程序是 不同步 的 一个线程在程序中和其他线程是异步运行的,在多处理器机器中一个线程可以同时与所有其他线程的实时运行其代码,这使得线程编程能够解决很复杂的事情,因 ...

  7. Unity在协程(Coroutines)内开启线程(Threading )

    孙广东  2017.6.13 http://blog.csdn.NET/u010019717 为什么要在协程中开启线程, 因为很多时候我们是需要线程执行完成后回到主线程的.然后主线程在继续执行后续的操 ...

  8. python中协程

    在引出协成概念之前先说说python的进程和线程. 进程: 进程是正在执行程序实例.执行程序的过程中,内核会讲程序代码载入虚拟内存,为程序变量分配空间,建立 bookkeeping 数据结构,来记录与 ...

  9. [Unity菜鸟] 协程Coroutine

    1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态. unity中StartCoroutine()就是协程,协程实际上是在一个线程中, ...

随机推荐

  1. ASP.NET CORE做的网站运行在docker上(不用dockerfile文件部署)

    按网上的做法用dockerfile文件是可以弄得出来的,http://www.docker.org.cn/article/119.html, 不过我想把网站文件放在外面硬盘目录,再映射进去,这样只要在 ...

  2. Socket网络编程--FTP客户端(2)(Windows)

    上一篇FTP客户端讲到如果制作一个简单的FTP客户端,功能实现了,但是后面我们发现了问题,就是FTP是使用明文进行操作的.对于普通情况来说就无所谓了.但有时候要安全的一点的话,就应该使用FTP的安全版 ...

  3. nfs 客户端启动报错rpc.mountd: svc_tli_create: could not open connection for tcp6

    # /etc/init.d/nfs start Starting NFS services: [ OK ] Starting NFS mountd: rpc.mountd: svc_tli_creat ...

  4. 使用 RestTemplate 调用 restful 服务

    什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效 ...

  5. iOS开发之按钮的基本使用

    实现功能: 点击向上的箭头,按钮图片向上,移动,点击向下的箭头,按钮图片向下移动 点击向左的箭头,按钮图片向左移动,点击向右的箭头,按钮图片向右移动, 点击加号图片放大,点击减号,图片缩小 第一步: ...

  6. 【Linux技术】磁盘的物理组织,深入理解文件系统

    磁盘即是硬盘,由许多块盘片(盘面)组成,每个盘片的上下两面都涂有磁粉,磁化后可以存储信息数据.每个盘片的上下两面都安装有磁头,磁头被安装在梳状的可以做直线运动的小车上以便寻道,每个盘面被格式化成有若干 ...

  7. MSTP故障处理手册

    H3C核心交换机常见故障定位手册.pdf MSTP故障处理手册.pdf 目 录 1 MSTP故障处理 1.1 广播风暴故障处理 1.1.1 故障描述 1.1.2 故障处理流程 1.1.3 故障处理步骤 ...

  8. js使用正则表达式实现文本框只能输入数字和小数点

    第一种情况:且限制小数点前最大3位数,小数点后最大3为三位 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN& ...

  9. html5+css3比较好的学习教程和demo效果

    1.css3 Animate.css 动画库--- http://daneden.github.io/animate.css/ 2.font-awesome 完美的图标字体,只为Bootstrap设计 ...

  10. hdu 4253(经典题目:二分+最小生成树)

    题意:就是说有A.B两个公司要修路,有m条路,可能是属于A修的,也可能是属于B修的,现在要求所有路都联通的情况下的最小权值,并且A公司必须要修k条路. 同: 代码: #include<iostr ...