进程-线程-多线程,同步和异步

1.什么是进程?

当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。

而一个进程又是由多个线程所组成的。


2.什么是线程?

线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。


3.什么是多线程?

多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

4.多线程的好处:

可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。


5.多线程的不利方面:

线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 

多线程需要协调和管理,所以需要CPU时间跟踪线程; 

线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;

线程太多会导致控制太复杂,最终可能造成很多Bug

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Threading;
  9 using System.Threading.Tasks;
 10 using System.Windows.Forms;
 11 
 12 namespace MyAsyncThread
 13 {
 14     /// <summary>
 15     /// 1 进程-线程-多线程,同步和异步
 16     /// 2 委托启动异步调用
 17     /// 3 多线程特点:不卡主线程、速度快、无序性
 18     /// 4 异步的回调和状态参数
 19     /// 5 异步等待三种方式
 20     /// 6 异步返回值
 21     /// 多线程是.Net开发非常重要的一块儿,
 22     /// 但是很多开发者工作多年,对多线程几乎不用/很畏惧/不明所以,写代码的时候没有考虑多线程的场景
 23     ///
 24     ///
 25     /// 进程:计算机概念,程序在服务器运行时占据全部计算资源综总和
 26     ///       虚拟的,
 27     /// 线程:计算机概念,进程在响应操作时最小单位,也包含CPU 内存  网络  硬盘IO
 28     ///       虚拟的概念,更加看不见摸不着
 29     /// 一个进程会包含多个线程;线程隶属于某个进程,进程销毁线程也就没了
 30     /// 句柄:其实是个long数字,是操作系统标识应用程序
 31     /// 多线程:计算机概念,一个进程有多个线程同时运行
 32     ///
 33     /// C#里面的多线程:
 34     /// Thread类是C#语言对线程对象的一个封装
 35     ///
 36     /// 为什么可以多线程呢?
 37     /// 1 多个CPU的核可以并行工作,
 38     ///   4核8线程,这里的线程指的是模拟核
 39     ///
 40     /// 2 CPU分片,1s的处理能力分成1000份,操作系统调度着去响应不同的任务
 41     ///   从宏观角度来说,感觉就是多个任务在并发执行
 42     ///   从微观角度来说,一个物理cpu同一时刻只能为一个任务服务
 43     ///
 44     /// 并行:多核之间叫并行
 45     /// 并发:CPU分片的并发
 46     ///
 47     /// 同步异步:
 48     ///       同步方法:发起调用,完成后才继续下一行;非常符合开发思维,有序执行;
 49     ///                 诚心诚意的请人吃饭,邀请Nick,Nick要忙一会儿,等着Nick完成后,再一起去吃饭
 50     ///       异步方法:发起调用,不等待完成,直接进入下一行,启动一个新线程来完成方法的计算
 51     ///                 客气一下的请人吃饭,邀请亡五,亡五要忙一会儿,你忙着我去吃饭了,你忙完自己去吃饭吧
 52     /// </summary>
 53     public partial class frmThreads : Form
 54     {
 55         public frmThreads()
 56         {
 57             //Thread
 58             InitializeComponent();
 59             Console.WriteLine("欢迎来到.net高级班vip课程,今天是Eleven老师带来的异步多线程内容");
 60         }
 61 
 62         #region Sync
 63         /// <summary>
 64         /// 同步方法
 65         /// </summary>
 66         /// <param name="sender"></param>
 67         /// <param name="e"></param>
 68         private void btnSync_Click(object sender, EventArgs e)
 69         {
 70             Console.WriteLine($"****************btnSync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
 71             int l = 3;
 72             int m = 4;
 73             int n = l + m;
 74             for (int i = 0; i < 5; i++)
 75             {
 76                 string name = string.Format($"btnSync_Click_{i}");
 77                 this.DoSomethingLong(name);
 78             }
 79             Console.WriteLine($"****************btnSync_Click   End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
 80 
 81         }
 82         #endregion
 83 
 84         #region Async
 85         /// <summary>
 86         /// 异步方法
 87         /// 1 同步方法卡界面:主线程(UI线程)忙于计算,无暇他顾
 88         ///   异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成
 89         ///   改善用户体验,winform点击个按钮不至于卡死;
 90         ///   web应用发个短信通知,异步多线程去发短信;
 91         ///
 92         /// 2 同步方法慢,只有一个线程计算
 93         ///   异步多线程方法快,因为5个线程并发计算
 94         ///   12658ms   3636ms  不到4倍   CPU密集型计算(资源受限)
 95         ///   10126ms    2075ms  差不多5倍,也不到5倍,Sleep(资源够用)
 96         ///   多线程其实是资源换性能,1 资源不是无限的  2 资源调度损耗
 97         ///
 98         ///   一个订单表统计很耗时间,能不能多线程优化下性能?  不能!这就是一个操作,没法并行
 99         ///   需要查询数据库/调用接口/读硬盘文件/做数据计算,能不能多线程优化下性能? 可以,多个任务可以并行
100         ///   线程不是越多越好,因为资源有限,而且调用有损耗
101         ///
102         /// 3 同步方法有序进行,异步多线程无序
103         ///   启动无序:线程资源是向操作系统申请的,由操作系统的调度策略决定,所以启动顺序随机
104         ///   同一个任务同一个线程,执行时间也不确定,CPU分片
105         ///   以上相加,结束也无序
106         ///   使用多线程请一定小心,很多事儿不是相当然的,尤其是多线程操作间有顺序要求的时候,
107         ///   通过延迟一点启动来控制顺序?或者预计下结束顺序?  这些都不靠谱!
108         ///
109         ///   需要控制顺序,晚点分解!
110         /// </summary>
111         /// <param name="sender"></param>
112         /// <param name="e"></param>
113         private void btnAsync_Click(object sender, EventArgs e)
114         {
115             Console.WriteLine($"****************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
116             Action<string> action = this.DoSomethingLong;
117 
118             //action.Invoke("btnAsync_Click_1");
119             //action("btnAsync_Click_1");
120 
121             //委托自身需要的参数+2个异步参数
122             //action.BeginInvoke("btnAsync_Click_1", null, null);
123 
124             for (int i = 0; i < 5; i++)
125             {
126                 string name = string.Format($"btnAsync_Click_{i}");
127                 action.BeginInvoke(name, null, null);
128             }
129 
130             Console.WriteLine($"****************btnAsync_Click End   {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
131         }
132         #endregion
133 
134 
135         #region Private Method
136         /// <summary>
137         /// 一个比较耗时耗资源的私有方法
138         /// </summary>
139         /// <param name="name"></param>
140         private void DoSomethingLong(string name)
141         {
142             Console.WriteLine($"****************DoSomethingLong Start  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
143             long lResult = 0;
144             for (int i = 0; i < 1_000_000_000; i++)
145             {
146                 lResult += i;
147             }
148             //Thread.Sleep(2000);
149 
150             Console.WriteLine($"****************DoSomethingLong   End  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
151         }
152         #endregion
153 
154         #region btnAsyncAdvanced_Click
155         private void btnAsyncAdvanced_Click(object sender, EventArgs e)
156         {
157             Console.WriteLine($"****************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
158 
159             //Action<string> action = this.DoSomethingLong;
160 
161             ////1 回调:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托
162             //IAsyncResult asyncResult = null;//是对异步调用操作的描述
163             //AsyncCallback callback = ar =>
164             //{
165             //    Console.WriteLine($"{object.ReferenceEquals(ar, asyncResult)}");
166             //    Console.WriteLine($"btnAsyncAdvanced_Click计算成功了。{ar.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
167             //};
168             //asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "花生");
169 
170             //////2 通过IsComplate等待,卡界面--主线程在等待,边等待边提示
171             //////( Thread.Sleep(200);位置变了,少了一句99.9999)
172             ////int i = 0;
173             ////while (!asyncResult.IsCompleted)
174             ////{
175             ////    if (i < 9)
176             ////    {
177             ////        Console.WriteLine($"中华民族复兴完成{++i * 10}%....");
178             ////    }
179             ////    else
180             ////    {
181             ////        Console.WriteLine($"中华民族复兴完成99.999999%....");
182             ////    }
183             ////    Thread.Sleep(200);
184             ////}
185             ////Console.WriteLine("中华民族复兴已完成,沉睡的东方雄狮已觉醒!");
186 
187             ////3 WaitOne等待,即时等待  限时等待
188             ////asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成
189             ////asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
190             ////asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超时就不等了
191 
192             ////4 EndInvoke  即时等待,而且可以获取委托的返回值 一个异步操作只能End一次
193             ////action.EndInvoke(asyncResult);//等待某次异步调用操作结束
194 
195             ////Console.WriteLine("全部计算成功了。。");
196 
197             Func<int> func = () =>
198             {
199                 Thread.Sleep(2000);
200                 return DateTime.Now.Hour;
201             };
202             int iResult = func.Invoke();//22
203             IAsyncResult asyncResult = func.BeginInvoke(ar =>
204              {
205                  //int iEndResultIn = func.EndInvoke(ar);
206              }, null);
207             int iEndResult = func.EndInvoke(asyncResult);//22
208 
209             Console.WriteLine($"****************btnAsync_Click End   {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
210         }
211         #endregion
212     }
213 }
View Code

 

posted @ 2021-11-25 22:32  少年,再不疯狂就老了  阅读(37)  评论(0)    收藏  举报