多线程编程学习笔记-基础(二)
2023-02-18 16:48:53 时间
接上文 多线程编程学习笔记-基础(一)
五、终止线程 (Abort)
1.代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; //引入线程 namespace ThreadConsoleApp { class Program { static void Main(string[] args) { Console.WriteLine("开始"); Thread t = new Thread(PrintNumberDely); //启动线程 t.Start(); Thread.Sleep(TimeSpan.FromSeconds(6)); //线程终止 t.Abort(); Console.WriteLine("线程终止"); Console.WriteLine("启动新线程"); t = new Thread(PrintNumber); t.Start(); PrintNumber(); Console.Read(); } static void PrintNumber() { Console.WriteLine("第四个多线程程序开始。。。。Second:" + DateTime.Now.Second); for (int i = 0; i <10; i++) { Console.WriteLine(string.Format("{0}",i)); } } /// <summary> /// 暂停2秒的方法 /// </summary> static void PrintNumberDely() { Console.WriteLine("第一个多线程终止程序开始。。。。"); for (int i = 0; i < 10; i++) { Console.WriteLine(string.Format("Second:{0} == {1}", DateTime.Now.Second, i)); Thread.Sleep(TimeSpan.FromSeconds(2)); } } } }
2.程序执行结果如下
从结果中,可以看出来,程序先启动了子线程的打印数字方法,在运行了6秒之后,调用了abort方法,终止了子线程。但是这个abort是通过注入ThreadAbortException方法,从而使用线程终止,这种方法非常危险,不建议使用。在子线程终止之后,主线程继续运行。
六、检测线程状态(ThreadState)
1.代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; //引入线程 namespace ThreadConsoleApp { class Program { static void Main(string[] args) { Console.WriteLine("开始"); Thread t = new Thread(PrintNumberStatus); Thread t2 = new Thread(DoNothing); //启动线程 t2.Start(); t.Start(); //显示线程状态 for (int i = 0; i < 10; i++) { Thread.Sleep(TimeSpan.FromMilliseconds(300)); Console.WriteLine(t.ThreadState.ToString()); } Thread.Sleep(TimeSpan.FromSeconds(4)); //线程终止 t.Abort(); Console.WriteLine("线程终止"); Console.WriteLine(string.Format("t线程状态:{0}", t.ThreadState.ToString())); Console.WriteLine(string.Format("t2线程状态:{0}", t2.ThreadState.ToString())); Console.Read(); } static void DoNothing() { Console.WriteLine("第五个多线程程序开始。。。。Second:" + DateTime.Now.Second); Thread.Sleep(TimeSpan.FromSeconds(2)); } /// <summary> /// 暂停2秒的方法 /// </summary> static void PrintNumberStatus() { Console.WriteLine("第五个多线程检测状态程序开始。。。。" + Thread.CurrentThread.ThreadState.ToString()); for (int i = 0; i < 10; i++) { Console.WriteLine(string.Format("Second:{0} == {1}", DateTime.Now.Second, i)); Thread.Sleep(TimeSpan.FromSeconds(2)); } } } }
2.程序执行结果如下
如上图,主线程启动时定义了两个子线程,一个会被终止,另一个会运行至结束。当我们启动了线程之后,t2线程的状态就会变成Running,然后会变成WaitSleepJoin,直到运行结束,变成Stopped。另一个t线程则会打印出数字来,当我们调用了abort方法之后,则t线程的状态就变成了AbortRequested。这充分说明了同步两个线程的复杂性,请不要程序中使用abort来终止线程。
七、线程优先级(Priority)
1.代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; //引入线程 using System.Diagnostics; namespace ThreadConsoleApp { class Program { static void Main(string[] args) { Console.WriteLine("开始,当前线程的优先级:"+Thread.CurrentThread.Priority); Console.WriteLine("线程运行多核CPU上"); //启动线程 Run(); Thread.Sleep(TimeSpan.FromSeconds(2)); //单核模拟 Console.WriteLine("线程运行单核CPU上"); Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1); Run(); Console.Read(); } static void Run() { var demo = new ThreadRunDemo(); Thread thread1 = new Thread(demo.CountNumber); thread1.Name = "ThreadOne"; Thread thread2 = new Thread(demo.CountNumber); thread2.Name = "ThreadTwo"; thread2.Priority = ThreadPriority.BelowNormal; Thread thread3 = new Thread(demo.CountNumber); thread3.Name = "ThreadThree"; thread1.Priority = ThreadPriority.Highest; thread2.Priority = ThreadPriority.AboveNormal; thread3.Priority = ThreadPriority.Lowest; thread1.Start(); thread2.Start(); thread3.Start(); Thread.Sleep(2000); demo.Stop(); } } class ThreadRunDemo { private bool isStopped = false; public void Stop() { isStopped = true; } public void CountNumber() { long cnt = 0; while(!isStopped) { cnt++; } Console.WriteLine(string.Format("线程 {0} 的优先级 {1,11} ,一共计算了 {2,13} 数字",
Thread.CurrentThread.Name,Thread.CurrentThread.Priority.ToString(), cnt.ToString("N0"))); } } }
2.程序执行结果如下
从上图的结果中,看出来当在多核CPU上运行多线程程序时,优先级所起到的作用区别不大,以上图的结果来看,最高优先级与最低优先级之间的差别在10%左右。如果在单核CPU上运行多线程程序时,优先级的作用的特别明显,以上图的结果来看,最高优先级与最低优先级之间的差别在100倍以上。
八、前台线程与后台线程
1.代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; //引入线程 using System.Diagnostics; namespace ThreadConsoleApp { class Program { static void Main(string[] args) { Console.WriteLine("开始,前台线程与后台线程"); var fore = new ThreadBackground(10); var back = new ThreadBackground(20); Thread threadF = new Thread(fore.CountNumber); threadF.Name = "前台线程"; Thread threadB = new Thread(back.CountNumber); threadB.Name = "后台线程"; threadB.IsBackground = true; //启动线程 threadF.Start(); threadB.Start(); //Console.Read(); } } class ThreadBackground { private int cnt ; public ThreadBackground(int count) { cnt = count; } public void CountNumber() { for (int i = 0; i < cnt; i++) { Thread.Sleep(500); Console.WriteLine(string.Format("线程 {0} 打印 {1,11} 数字", Thread.CurrentThread.Name, i.ToString("N0"))); } Console.WriteLine("{0} finished counting.", Thread.CurrentThread.IsBackground ? "Background Thread" : "Foreground Thread"); } } }
2.程序执行结果
根据上面的代码,当程序执行到如上图时,会一闪而过,退出。这是因为前台线程已经执行结束,虽然后台线程没有执行结束,但程序会自动终止后台线程。这就是前台线程与后台线程的区别,进程会等所有的前台线程执行完毕,如果此时只剩下后台线程没有执行完毕,则会直接结束工作。
相关文章
- [html] 同一页面的跳转,锚文本的使用方法
- [PHP] 解决宝塔面板运行php项目 pcntl_fork() has been disabled for security reasons
- abp(net core)+easyui+efcore实现仓储管理系统——EasyUI前端页面框架 (十八)
- 学习ASP.NET Core Razor 编程系列十二——在页面中增加校验
- 学习ASP.NET Core Razor 编程系列七——修改列表页面
- 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面
- 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面
- 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面
- 初探语音识别ASR算法
- 撬动百亿VRAR产业,让VR们“造”起来
- 今天谈谈用户故事地图,不是用户故事
- 带你掌握二进制SCA检测工具的短板及应对措施
- 云图说|ModelArts Pro:让AI开发更简单
- HDZ城市行深圳站|AIoT时代,如何抓住智联生活的战略机会点?
- 1个通用工具平台+多个热点场景工具套件,助力开发者快速构建应用
- 左手自研,右手开源,技术揭秘华为云如何领跑容器市场
- 云小课|DGC数据开发之基础入门篇
- 图解带你掌握`JVM`运行时核心内存区
- TCP 两次握手为什么无法阻止历史连接?
- AI新手语音入门:认识词错率WER与字错率CER