《创建多线程程序.ppt》由会员分享,可在线阅读,更多相关《创建多线程程序.ppt(47页珍藏版)》请在三一办公上搜索。
1、第十一章 创建多线程程序,沈项军计算机科学与通信工程学院,2,内容提要,实现线程定义线程的生命周期实现多线程识别线程的优先级在线程中使用同步识别进程间的通信,3,同时执行所有任务,时间更少,效率更高,线程简介,在同一时间点执行各项进程,编译程序 发送/接收邮件 打印文件 其他,操作系统允许计算机同时执行多项操作,程序(进程),4,线程简介,程序 1,程序 2,线程 1,线程 2,线程 3,线程 1,线程 2,线程 3,单独的执行路径,多线程,5,进程和线程,进程是程序的一次执行一个或多个线程构成一个进程,进程,线程,6,线程简介,在以下情况中可能要使用到多线程:,程序需要同时执行两个或多个任务
2、,程序要等待某事件的发生,例如用户输入、文件操作、网络操作、搜索等,后台程序,7,线程及多线程工作原理,线程表示计算机执行的指令序列。一个处理器在某一刻只能处理一个任务。如果有一个多处理器系统,理论上它可以同时执行多个指令一个处理器执行一个指令,但大多数人使用的是单处理器计算机,这种情况是不可能同时发生的。而实际上,Windows操作系统表面上可以同时处理多个任务,这个过程称为抢先式多任务处理(pre-emptive multitasking)。,8,抢先式多任务处理,所谓抢先式多任务处理,是指Windows在某个进程中选择一个线程,该线程运行一小段时间。Microsoft没有说明这段时间有多
3、长,因为为了获得最好的性能,Windows有一个内部操作系统参数来控制这个时间值。但在运行Windows应用程序时,用户不需要知道它。从我们的角度来看,这个时间非常短,肯定不会超过几毫秒。这段很短的时间称为线程的时间片(time slice)。过了这个时间片后,Windows就收回控制权,选择下一个被分配了时间片的线程。这些时间片非常短,我们可以认为许多事件是同时发生的。,9,实现线程,线程被用来运行完成大型和复杂计算的程序。使用一个线程执行的进程被称为单线程进程,这里进程是一个程序的运行实例。单线程程序一次仅可以完成一个任务。在另一个任务开始之前,你必须等待一个任务完成。,10,实现线程,下
4、图显示了单线程进程。为了一次执行多于一个任务,你可以在程序中创建多个线程。创建两个或更多线程的进程被称为多线程进程。,11,C#中的线程模型,在单线程模型中,程序使用轮询来调用事件循环。轮询是一个进程,在其中一次执行一个单一的事件。在带有轮询方法的事件循环中,单一线程以无限循环的方式运行直到它的操作完成。在单线程程序中,如果线程从执行被挂起因为它正在等待一个系统资源,整个程序停止执行。在多线程中,一个线程等待的CPU时间可以被用来完成另一个任务。,12,C#中的线程模型,在CLR中有两种线程代表托管线程代表OS线程using System;class HelloWorld static voi
5、d Main()Console.WriteLine(Hello,World);Console.ReadLine();,13,主线程,主线程在C#程序开始执行的时候被自动创建。使用Thread类被排他创建的线程被称为子线程,其中主线程被称为父线程或者基本线程。你可以使用Thread类的CurrentThread属性来访问线程。,14,使用线程,在C#中,通过ThreadStart创建线程调用方法的引用,并将该引用通过创建一个Thread类型的对象创建一个线程,接着调用新线程的Start()方法启动线程。ThreadStart ChildRef=new ThreadStart(ChildThrea
6、dCall);Thread ChildThread=new Thread(ChildRef);ChildThread.Start();,引用System.Threading 命名空间,Thread 线程实例名=new Thread(new ThreadStart(方法名);,只创建但不启动线程,线程实例名.Start();,启动线程,15,使用线程,新线程开始异步执行线程的方法调用。线程的处理启动线程(Start方法)挂起线程(Suspend方法)挂起不会立即生效恢复被刮起的线程(Resume方法)恢复不会立即生效终止线程(Abort方法)线程的休眠(Sleep方法),16,管理线程,有许多你
7、可能需要完成的任务来管理线程的活动或生命。可以通过使用Thread类的各种可用线程方法来管理这些任务。Thread.Sleep()静态方法调用静态CurrentThread方法,然后它在指定的时间内暂停线程。,17,管理线程,临时挂起会话进程(用户通常不会这么做,但这仅是一个示例,在更真实的示例中,用户可能是暂停声音文件或视频文件的播放)。在主线程中编写如下代码,挂起该线程:depthChangeThread.Suspend();如果需要恢复该线程,可以使用下面的方法:depthChangeThread.Resume();如需要退出该线程depthChangeThread.Abort();,1
8、8,线程使用示例,using System;using System.Threading;class BasicThreadApp public static void ChildThreadCall()try Console.WriteLine(Child thread started);Console.WriteLine(Child thread-counting to 10);for(int i=0;i 10;i+)Thread.Sleep(500);Console.Write(0.,i);Console.WriteLine(Child thread finished);catch(Th
9、readAbortException e)Console.WriteLine(Exception has caught);finally Console.WriteLine(Child Thread-unable to be finished);,public static void Main()ThreadStart ChildRef=new ThreadStart(ChildThreadCall);Console.WriteLine(Main-Creating Child Thread);Thread ChildThread=new Thread(ChildRef);ChildThread
10、.Start();Console.WriteLine(Main-Sleeping for 2 seconds);Thread.Sleep(2000);Console.WriteLine(n Main-Aborting child thread);ChildThread.Abort();Console.ReadLine();,19,线程生命周期,当类的对象被创建的时候,线程的生命周期开始。线程的生命周期结束于任务的执行。在线程的生命周期中有各种状态。这些状态是:未启动状态运行态未运行态死亡态,20,未启动状态,当一个Thread类的实例被创建的时候,线程进入未启动状态。新线程是Thread类的一
11、个空对象,没有系统资源例如内存被分配给它。,21,运行态,线程一直处在未启动状态直到程序调用Thread类的Start()方法,它将线程置于运行态,并且立即返回控制到调用的线程。这个状态也被称为准备或启动状态。新启动的线程和程序中任何其它线程同时执行。,22,Start(),Started,Work Completed,Stopped,线程生命周期,23,未运行态,如果它处于下面的状态,那么线程处于未运行态休眠等待阻塞,24,Start(),Started,Suspend(),Suspended,Resume(),线程生命周期,25,Start(),Started,Sleep(),Wait/J
12、oinSleep,Interrupt(),Time Expires,线程生命周期,26,死亡状态,当线程方法的语句完成的时候,运行线程进入死亡状态。这个状态也被称为终结态。程序可以通过在适当的线程对象上调用Thread类的Abort()方法来强迫线程进入死亡态。,27,Start(),Started,Abort(),Stop Request,Thread Responds to Stop Request,Stopped,线程生命周期,28,介绍多线程,多线程有助于同时完成各种操作,节省用户的时间。多线程允许你在一个程序中完成多个任务。多任务是同时执行多个任务的能力。多任务可以被分成如下类型:基
13、于进程的多任务 基于线程的多任务,该女士在同时吃苹果、看书并在电脑上工作。,29,多线程的优点和限制,多线程的优点有:改进性能 最小化系统资源 同时访问多个程序 程序结构简化 多线程的限制有:竞态情况同时读写同一个变量死锁情况互相等待对方释放所需资源饥饿锁低优先级的线程无限等待,30,创建多线程示例,using System;using System.Threading;class ThreadSchedule public static void ChildThread1()Console.WriteLine(Child thread 1 started);Console.WriteLine
14、(Child thread-counting from 1 to 10);for(int T=1;T 11;T+)for(int Cnt=0;Cnt 100;Cnt+)Console.Write(.);Console.Write(0,T);Console.WriteLine(Child thread 1 finished);public static void ChildThread2()Console.WriteLine(Child thread 2 started);Console.WriteLine(Child thread-counting slowly from 11 to 20);
15、for(int T=11;T 21;T+)for(int Cnt=0;Cnt 100;Cnt+)Console.Write(.);Console.Write(0,T);Console.WriteLine(Child thread 2 finished);,public static void Main()ThreadStart Child1=new ThreadStart(ChildThread1);ThreadStart Child2=new ThreadStart(ChildThread2);Console.WriteLine(Main-Creating Child Threads);Th
16、read Thread1=new Thread(Child1);Thread Thread2=new Thread(Child2);Thread1.Start();Thread2.Start();,31,确定线程的优先级,控制线程行为的一个属性是它的优先级。.NET运行环境基于它们的优先级执行线程。线程是固定优先级的调度的。带有优先级的每个线程在处理器的线程队列中有自己的位置。,32,定义线程优先级,线程优先级是指定一个线程相对于另一个线程的优先级的属性。线程的优先级可以被定义为:最高(Highest)正常以上(AboveNormal)正常(Normal)正常以下(BelowNormal)最低
17、(Lowest)高优先级的线程在低优先级的线程之前运行。如果C#遇到了另一个优先级更高的线程,当前线程被推后;高优先级的程序被执行。,33,设置线程的优先级,可以在创建了线程之后使用Thread类的Priority属性设置线程的优先级。下面的语法显示如何设置线程的优先级:ThreadStart workerStart=new ThreadStart(StartMethod);Thread workerThread=new Thread(workerStart);workerThread.Name=Worker;workerThread.Priority=ThreadPriority.Above
18、Normal;workerThread.Start();,34,设置线程的优先级,如果有多个有相同优先级的线程,调度器在同一优先级循环执行线程,假设每个线程执行的时间片是固定的。只要高优先级的线程可以运行,低优先级的线程就不能被执行。当在给定的优先级没有可运行的线程的时候,调度器移动到下一个低优先级,调度那个优先级的线程执行。,35,线程的调度,CLR把所有处于执行状态(runnable)的线程,按照优先级的不同分别放置在不同的池中。当一个阻塞的线程变为runnable状态时,它被放置到相应的池中。具有最高优先级的非空线程池中的线程被赋予CPU时间。,36,在线程中使用同步,使用线程的一个重要
19、方面是同步访问多个线程访问的任何变量。所谓同步,是指在某一时刻只有一个线程可以访问变量。如果不能确保对变量的访问是同步的,就会产生错误。,37,同步线程,线程的同步确保如果两个或更多线程需要访问一个共享的资源,那么那个资源一次仅有一个线程可以使用。可以使用synchronized关键字来同步代码。同步是基于监视的概念的。监视器是用做锁定数据成员和类的方法的对象。,38,同步线程,39,使用监视器锁锁定代码,System.Monitor类使你能够通过使用锁和信号来序列化代码锁的访问。用Monitor.Enter方法锁住资源用Monitor.Exit方法释放锁,40,使用监视器锁的示例,书上例子,
20、41,使用带有C#Lock语句的监视器锁,另一个锁定代码的方法是使用C#lock语句。尽管C#lock语句不支持Monitor类中的全部集合特性,但它使你能够获得和释放一个监视器的锁。其用法如下所示:lock(x)DoSomething();,42,Lock语句示例,书店可能某种书籍只有一本,而两个售货员同时销售这本书,我们可以把两个售货员看作两个线程,那该如何处理呢?,using System;using System.Threading;public class BookShop public int num=1;/共享资源 public void Sale()int tmp;lock(t
21、his)/同步控制 tmp=num;if(tmp 0)/卖书过程 Thread.Sleep(1000);num=num-1;Console.WriteLine(售出一本);else Console.WriteLine(没有了);,public class MyClass public static void Main()BookShop a=new BookShop();Thread t1=new Thread(new ThreadStart(a.Sale);Thread t2=new Thread(new ThreadStart(a.Sale);t1.Start();t2.Start();C
22、onsole.Read();,43,同步注意问题,不要滥用同步 死锁 竞态条件,44,识别进程间的通信,进程是程序的一个运行实例。运行时在同一计算机内或通过网络的进程间的通信被称为进程间通信。为了允许进程间通信,使用特殊技术和机制。,45,程序域,在.NET中,线程在程序域中执行。在一个进程中的线程不能调用属于另一个进程中的线程的方法。但是,在.NET中,线程可以通过程序域的边界,在一个线程的方法可以调用另一个程序域的方法。程序域是物理进程内的逻辑进程。,46,程序域,程序域的主要目的是从其他程序中隔离你的程序。程序域在单个进程运行。使用System.AppDomain类来管理程序域。,47,作业,练习1,