计算机概念
进
计算机概念
进程
程序在服务器运行时,占据的计算资源合计,称之为进程。进程之间不会相互干扰,但是进程间的通信比较困难(分布式)。
线程
程序执行的最小单位,相应操作的最小执行流,线程也包含自己的计算资源。线程是属于进程的,一个进程可以有多个线程。
多线程
一个进程里面,有多个线程并发执行
C#
多线程Thread
`Thread`是一个类,就是一个封装,是.NET对线程对象的抽象封装,通过`Thread`去完成的操作,最终是通过像操作系统请求得到的执行流
* `CurrentThread`:当前线程–任何操作执行都是线程完成的,即获得运行当前这句话的线程
* `ManagerThreadId`:是.NET平台给Thread起的名字,就是一个`int`值,尽量不重复
* 同步单线程方法:按顺序执行,每次调用完成后才能进下一行,是同一个线程运行的
* 异步多线程方法:发起调用,不等待结果就直接进入下一行(主线程),动作会由一个新线程来执行(子线程)
特点
界面卡顿
* 同步单线程方法卡界面 —- 主(UI)线程线程忙于计算,所以不能相应
* 异步多线程不卡界面 —- 计算任务交给子线程,主(UI)线程已经闲置,可以相应别的操作
* 多线程对于C/S:点击按钮后能不卡死,例如:上传文件界面不卡死
* 多线程对于B/S:例如:用户注册时同时发邮件/发短信/写日志
执行速度
* 同步单线程方法慢 —- 因为只有一个线程在计算
* 异步多线程方法快 —- 因为多个线程并发计算
* 多线程就是用资源换性能
* 但是两者的速度差不是线性增长,例如1个线程耗时1000毫秒,5个线程不代表能做到耗时200毫秒。说明多线程的协调管理由额外的成本,同时资源也是由上限的
* 所以:线程并不是越多越好
无序性
* 启动无序:几乎同一时间向操作系统请求线程,因为线程时操作系统资源,CLR只能去申请,具体时什么顺序启动这个无法掌握
* 执行时间不确定:同个线程同个任务耗时都不一样,更何况多个任务多个线程。这跟操作系统的资源调度策略有关
* 结束无序:上面的都无序,结束时间怎么可能有序
注意
使用多线程时,千万不要通过延时等方式去掌控顺序
多线程控制顺序
异步回调
死循环IsCompleted等待
信号量
EndInvoke获得返回值
使用各个版本的多线程处理方式
Thread
示例:
1 2 3 4 5 6 7 8 9 10
|
ThreadStart threadHandler = () => { Console.WriteLine($"Thread Start。。。{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(2000); Console.WriteLine($"Thread End。。。{Thread.CurrentThread.ManagedThreadId}"); }; var thread = new Thread(threadHandler); thread.Start();
|
ThreadPool
示例:
1 2 3 4 5 6 7 8 9 10 11
|
WaitCallback callback = o => { Console.WriteLine($"ThreadPool Start。。。{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(2000); Console.WriteLine($"ThreadPool End。。。{Thread.CurrentThread.ManagedThreadId}"); }; ThreadPool.QueueUserWorkItem(callback);
|
Task
示例:
1 2 3 4 5 6 7 8 9 10
|
Action action = () => { Console.WriteLine($"Task Start。。。{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(2000); Console.WriteLine($"Task End。。。{Thread.CurrentThread.ManagedThreadId}"); }; Task task = new Task(action); task.Start();
|
Parallel
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
Parallel.Invoke(() => { Console.WriteLine($"Parallel 1 Start。。。{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(2000); Console.WriteLine($"Parallel 1 End。。。{Thread.CurrentThread.ManagedThreadId}"); }, () => { Console.WriteLine($"Parallel 2 Start。。。{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(2000); Console.WriteLine($"Parallel 2 End。。。{Thread.CurrentThread.ManagedThreadId}"); }, () => { Console.WriteLine($"Parallel 3 Start。。。{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(2000); Console.WriteLine($"Parallel 3 End。。。{Thread.CurrentThread.ManagedThreadId}"); });
|
Task比较全面示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| public void Coding(string dev, string module) { var random = new Random(); var stopWatch = new Stopwatch(); stopWatch.Start(); Console.WriteLine($"{dev}开发{module}模块 开始.......... ManagedThreadId={Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(random.Next(1000, 5000)); stopWatch.Stop(); Console.WriteLine($"{dev}开发{module}模块 完成.......... ManagedThreadId={Thread.CurrentThread.ManagedThreadId} 共耗时{stopWatch.ElapsedMilliseconds}毫秒"); } public void AllJob() { Console.WriteLine("谈需求..."); Console.WriteLine("选成员..."); Console.WriteLine("分配模块..."); List<Task> tasks = new List<Task>(); tasks.Add(Task.Run(() => Coding("张小三", "用户管理"))); tasks.Add(Task.Run(() => Coding("李筱思", "商品管理"))); tasks.Add(Task.Run(() => Coding("王小五", "订单管理"))); tasks.Add(Task.Run(() => Coding("赵小六", "售后管理"))); TaskFactory taskFactory = new TaskFactory(); taskFactory.ContinueWhenAny(tasks.ToArray(), t => { Console.WriteLine($"达到里程碑... ManagerThreadId={Thread.CurrentThread.ManagedThreadId}"); }); taskFactory.ContinueWhenAll(tasks.ToArray(), tArray => { Console.WriteLine($"项目上线... ManagerThreadId={Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine($"项目验收... ManagerThreadId={Thread.CurrentThread.ManagedThreadId}"); Console.WriteLine($"支付费用... ManagerThreadId={Thread.CurrentThread.ManagedThreadId}"); });
Task.WaitAny(tasks.ToArray()); Console.WriteLine("达到里程碑..."); Task.WaitAll(tasks.ToArray()); Console.WriteLine("项目上线..."); Console.WriteLine("项目验收..."); Console.WriteLine("支付费用...");
}
|
多线程安全
如果一段代码,单线程执行和多线程执行结果不一致,就表明由线程安全问题