多线程概念
什么是多线程?多线程是应用程序中多个可以并发或顺序执行的任务,这些任务共用应用程序占有的系统资源包括内存以及其它的物理资源。
一、创建线程
Thread类的构造函数由四种形式,两种使用ParameterizedThreadStart 委托实例,使用这种委托初始化的线程执行的方法可以带参数,参数在线程启动时候指定,另外两种是使用ThreadStart委托实例,使用这种委托初始化Thread实例执行的线程方法不带参数;maxStackSize指定线程堆栈大小,一般不指定堆栈大小。
public Thread(ParameterizedThreadStart start); public Thread(ParameterizedThreadStart start, int maxStackSize); public Thread(ThreadStart start, int maxStackSize); public Thread(ThreadStart start);
知道了怎么创建线程,显摆下先。代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Threading; //注意此处添加引用。 namespace ThreadDemoCreateThead { class Program { static void Main(string[] args) { //无参数方法创建新线程 Thread threadWithoutParam = new Thread(WriteString); //启动线程 threadWithoutParam.Start(); string str = "带参数启动线程调用方法"; //带参数方法创建新线程 Thread threadWithParam = new Thread(WriteStringWithPara); //启动线程。 threadWithParam.Start(str); Console.ReadKey(); } /// <summary> /// 无参数方法 /// </summary> static void WriteString() { Console.WriteLine("无参数启动线程调用方法"); } /// <summary> /// 参数方法,参数只能中object类型 /// </summary> /// <param name="obj"></param> static void WriteStringWithPara(object obj) { Console.WriteLine(obj.ToString()); } } }
结果如下图:
二、线程的属性
线程常用属性用说明如下:
Name | 获取或设置线程的名称 |
Priority | 获取或设置线程的优先级 |
ThreadStates | 获取包含当前线程状态的值 |
IsThreadPoolThread | 获取值指示线程是否是线程池中的线程 |
IsAlive | 获取当前线程运行状态的值 |
IsBackground | 获取或设置表示当前线程是否为后台线程的值 |
CurrentThread | 静态属性获取当前运行的线程 |
CurrentContext | 静态属性获取线程执行的当前上下文环境 |
CurrentPrinciple | 静态属性获取或设置当前线程的负责人,基于角色的安全性 |
再看看线程的属性,代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Threading; //注意此处添加引用。 namespace ThreadDemoCreateThead { class Program { static void Main(string[] args) { //无参数方法创建新线程 Thread threadWithoutParam = new Thread(WriteString); threadWithoutParam.Name = "无参委托线程"; //注意此处设置线程名称 //启动线程 threadWithoutParam.Start(); string str = "带参数启动线程调用方法"; //带参数方法创建新线程 Thread threadWithParam = new Thread(WriteStringWithPara); //启动线程。 threadWithParam.Start(str); Console.ReadKey(); } //修改了无参数委托方法使用线程中的属性。 /// <summary> /// 无参数方法 /// </summary> static void WriteString() { Console.WriteLine("无参数启动线程调用方法"); Console.WriteLine("线程名称"+Thread.CurrentThread.Name); Console.WriteLine("线程状态"+Thread.CurrentThread.ThreadState); Console.WriteLine("线程优先级" + Thread.CurrentThread.Priority); Console.WriteLine("线程是否正在运行" + Thread.CurrentThread.IsAlive); Console.WriteLine("线程是否是后台线程" + Thread.CurrentThread.IsBackground); Console.WriteLine("结束无参数启动线程调用方法"); } /// <summary> /// 参数方法,参数只能中object类型 /// </summary> /// <param name="obj"></param> static void WriteStringWithPara(object obj) { Console.WriteLine(obj.ToString()); } }
结果如下图:
三、线程的方法
使用最多的是线程的实例方法如下:
Start() | 启动线程 |
Sleep() | 将线程挂起指定时间或者指定时间间隔 |
Join() | 被调用线程执行,在被调用线程结束前调用方将等待。 |
Suspend() | 挂起线程,否决的。 |
Resume() | 继续挂起的线程,否决的。 |
Abort() | 终止线程,引发线程终止异常 |
四、线程的状态和生命周期
通过上面线程方法的介绍,可以很自然的看到线程的生命周期包括这几个阶段:未启动、启动、睡眠、中断、结束。线程的生命周期不同时期又对应不同的线程状态,线程状态包括下面几种:Unstarted、StopRequested、SuspendRequested、Background、Stopped、WaitSleepJoin、Suspended、Running、AbortRequested、Aborted。
由于线程的方法和线程的状态和生命周期相关所以代码一起展示,如下:
using System; using System.Collections.Generic; using System.Text; using System.Threading; //注意此处添加引用。 namespace ThreadDemoCreateThead { class Program { static void Main(string[] args) { //无参数方法创建新线程 Thread threadWithoutParam = new Thread(WriteString); threadWithoutParam.Name = "无参委托线程"; //注意此处设置线程名称 //线程状态 Console.WriteLine("新线程当前状态:" + threadWithoutParam.ThreadState); //启动线程 threadWithoutParam.Start(); for (int i = 0; i < 5; i++) { Thread.Sleep(10); if (i != 3) { Console.WriteLine("主线程在工作"); } else { Console.WriteLine("新线程加入,主线等待新线程结束。"); threadWithoutParam.Join(); } } Console.WriteLine("新线程当前状态:" + threadWithoutParam.ThreadState); Console.ReadKey(); } //修改了无参数委托方法使用线程中的属性。 /// <summary> /// 无参数方法 /// </summary> static void WriteString() { Console.WriteLine("无参数启动线程调用方法"); Console.WriteLine("新线程当前状态:" + Thread.CurrentThread.ThreadState); for (int i = 0; i < 5; i++) { Thread.Sleep(10); Console.WriteLine("新线程在工作"); } try { Thread.CurrentThread.Abort(); } catch (ThreadAbortException ex) { Console.WriteLine("终止自身时候发生了异常"); } Console.WriteLine("结束无参数启动线程调用方法"); } } }
结果应该如下图所示:
创建线程是很容易的,已经学会了创建线程,理解线程的属性,学会使用了线程中的方法,再来个示例练习下,代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Threading; //注意此处添加引用。 namespace ThreadDemoCreateThead { class Program { static int nums = 1000; static void Main(string[] args) { Thread thread1 = new Thread(PlusNum); Thread thread2 = new Thread(PlusNum); thread1.Name = "线程1"; thread2.Name = "线程2"; thread1.Start(); thread2.Start(); Console.ReadKey(); } // /// <summary> /// 加法运算 /// </summary> /// <param name="num"></param> static void PlusNum() { Console.WriteLine( Thread.CurrentThread.Name+"Num当前值是:" + nums); Thread.Sleep(100); nums -= 1000; Console.WriteLine(Thread.CurrentThread.Name + "Num操作减1000后是:" + nums); // } } }
运行结果如下图:
再次运行结果如下图:
如果多次运行可能还有别的结果,为什么同样的程序多次运行结果会不同?两个线程操作同个数字会出现不同的结果,如果操作的是非常重要的数据,比如银行账号余额,后果非常可怕,应该怎么处理这样的操作呢?请看:线程同步