CPU总是运行一个进程,其他进程处于非运行状态,一个进程可以包含多个线程,每个线程可以使用进程的共享空间
互斥锁:防止多个线程同时读写某一块内存区域
信号量:用来保证多个线程不会互相冲突
一个线程里的语句是从上到下的,多线程编程是同步的,看里头代码的消耗时间
static int Test(int i,string str) 一般我们会为比较耗时的操作 开启单独的线程去执行,比如下载操作
{
Debug.Log("test"+i+str);
Thread.Sleep(100); 让当前线程休眠(暂停线程的执行) 单位ms using System.Threading
return 100;
}
1.通过委托开启一个线程
Func
IAsyncResult ar=a.BeginInvoke(100,"siki",null,null); 开启一个新的线程去执行 a所引用的方法
//IAsyncResult 可以取得当前线程的状态
可以认为线程是同步执行的(异步执行)
Debug.Log("main");
While(ar.IsCompleted==false) 如果线程没有执行完毕
{
Debug.Log(".");
Thread.Sleep(10);
}
int res=a.EndInvoke(ar); 取得异步线程的返回值
Debug.Log(res);
(2)检测线程结束
Bool isEnd=ar.AsyncWaitHandle.WaitOne(1000); 1000毫秒表示超时时间,如果等待了1000毫秒线程还没有结束的话,那这个方法返回false,如果在1000毫秒内线程结束了,那这个方法返回true;
if(IsEnd)
{
int res=a.EndInvoke(ar);
Debug.Log(res);
}
(3)用回调函数检测线程结束
Func
倒数第二个参数是一个委托类型的参数,表示回调函数,就是当线程结束的时候会调用这个委托指向的方法,倒数第一个参数用来给回调函数传递数据
a.BeginInvoke(10,"siki",ar=>
{
int res=a.EndInvoke(ar);
Debug.Log(res+"在Lambda表达式取得");
},null);
using System.Threading
Thread t=new Thread(()=> 创建一个线程
{
Debug.Log("开始下载"+Thread.CurrentThread.ManagedThreadId); 获得当前线程的ID
Thread.Sleep(2000);
Debug.Log("完成下载");
});
t.Start(); 开始去执行线程
(2)也可以传一个方法DownloadFile (传递一个参数)
static void DownloadFile(object filename)
{
Debug.Log("开始下载"+Thread.CurrentThread.ManagedThreadId+filename);
Thread.Sleep(2000);
Debug.Log("完成下载");
}
Thread t=new Thread(DownloadFile);
t.Start("xxx.bt");
第二种传递参数的方法,建立一个Thread类
Public class MyThread
{
private string filename;
private string filepath;
MyThread(string filename,string filepath)
{
this.filename=filename;
this.filepath=filepath;
}
public void DownFile()
{
Debug.Log("开始下载"+filename+filepath);
Thread.Sleep(2000);
Debug.Log("完成下载");
}
}
MyThread my=new MyThread("xxx.bt","http:\\www.xxx.com");
Thread t=new Thread(my.DownFile) 我们构造一个thread对象的时候,可以传递一个静态方法,也可以传递一个对象的普通方法
t.Start();
前台线程和后台线程:
只有一个前台线程在运行,应用程序的进程就在运行,判断前台线程是否结束决定程序是否在运行
用Thread类创建的线程是前台线程,线程池中的线程总是后台线程
Thread t=new Thread();
t.IsBackground(true); 把前台线程变成后台线程
t.Abort() 停止线程方法,会抛出一个ThreadAbortException类型的异常
适合于时间较短的任务,如果进程的所有前台线程都结束了,所有的后台线程就会停止
ThreadPool.QueneUserWorkItem(ThreadMethod); 开启一个工作线程
线程池所有线程都是后台线程,不能修改成前台线程,也不能修改线程池优先级或名称
Task t=new Task(ThreadMethod); 传递一个需要线程去执行的方法
t.Start();
第二种方法:
TaskFactory tf=new TaskFactory(); 开启任务
Task t=tf.StartNew(ThreadMethod);
连续任务:
Task t1=new Task(doFirst);
Task t2=t1.ContinueWith(doSecond);
Task t3=t1.ContinueWith(doSecond);
Task t4=t2.ContinueWith(doSecond);
解决争用问题:(多个线程进行)
Lock(m) 向系统申请可不可以 锁定m对象,如果m对象没有被锁定,那么可以 如果m对象被锁定了,那么这个语句就会暂停,知道申请到m对象
{
m.ChangeState(); 在同一时刻,只有一个线程在执行这个方法
} 释放对m的锁定