Thread--线程
Posted yzm97
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thread--线程相关的知识,希望对你有一定的参考价值。
下面语句来源自朝夕教育 Eleven老师
1 进程-线程-多线程,同步和异步
2 委托启动异步调用
3 多线程特点:不卡主线程、速度快、无序性
4 异步的回调和状态参数
5 异步等待三种方式
6 异步返回值
多线程是.Net开发非常重要的一块儿,
但是很多开发者工作多年,对多线程几乎不用/很畏惧/不明所以,写代码的时候没有考虑多线程的场景
进程:计算机概念,程序在服务器运行时占据全部计算资源综总和
虚拟的,
线程:计算机概念,进程在响应操作时最小单位,也包含CPU 内存 网络 硬盘IO
虚拟的概念,更加看不见摸不着
一个进程会包含多个线程;线程隶属于某个进程,进程销毁线程也就没了
句柄:其实是个long数字,是操作系统标识应用程序
多线程:计算机概念,一个进程有多个线程同时运行
C#里面的多线程:
Thread类是C#语言对线程对象的一个封装
为什么可以多线程呢?
1 多个CPU的核可以并行工作,
4核8线程,这里的线程指的是模拟核
2 CPU分片,1s的处理能力分成1000份,操作系统调度着去响应不同的任务
从宏观角度来说,感觉就是多个任务在并发执行
从微观角度来说,一个物理cpu同一时刻只能为一个任务服务
并行:多核之间叫并行
并发:CPU分片的并发
同步异步:
同步方法:发起调用,完成后才继续下一行;非常符合开发思维,有序执行;
诚心诚意的请人吃饭,邀请Nick,Nick要忙一会儿,等着Nick完成后,再一起去吃饭
异步方法:发起调用,不等待完成,直接进入下一行,启动一个新线程来完成方法的计算
客气一下的请人吃饭,邀请亡五,亡五要忙一会儿,你忙着我去吃饭了,你忙完自己去吃饭吧
1 thread:线程等待,回调,前台线程/后台线程
2 threadpool:线程池使用,设置线程池,ManualResetEvent
3 扩展封装thread&threadpool回调/等待
1 Task:Waitall WaitAny Delay
2 TaskFactory:ContinueWhenAny ContinueWhenAll
3 并行运算Parallel.Invoke/For/Foreach
1 多异常处理和线程取消
2 多线程的临时变量
3 线程安全和锁lock
4 await/async
/// 多线程1.0
/// Thread:C#对线程对象的一个封装
/// Thread方法很多很强大,但是也太过强大,而且没有限制
{
ThreadStart method = () =>
{
Thread.Sleep(5000);
this.DoSomethingLong("btnThread_Click");
Thread.Sleep(5000);
};
Thread thread = new Thread(method);
thread.Start();//开启线程,执行委托的内容
//thread.Suspend();//暂停
//thread.Resume();//恢复 真的不该要的,暂停不一定马上暂停;让线程操作太复杂了
//thread.Abort();
////线程是计算机资源,程序想停下线程,只能向操作系统通知(线程抛异常),
////会有延时/不一定能真的停下来
//Thread.ResetAbort();
//1等待
//while (thread.ThreadState != ThreadState.Stopped)
//{
// Thread.Sleep(200);//当前线程休息200ms
//}
//2 Join等待
//thread.Join();//运行这句代码的线程,等待thread的完成
//thread.Join(1000);//最多等待1000ms
//Console.WriteLine("这里是线程执行完之后才操作。。。");
//thread.Priority = ThreadPriority.Highest;
////最高优先级:优先执行,但不代表优先完成 甚至说极端情况下,还有意外发生,不能通过这个来控制线程的执行先后顺序
thread.IsBackground = false;//默认是false 前台线程,进程关闭,线程需要计算完后才退出
//thread.IsBackground = true;//关闭进程,线程退出
}
1 //基于thread封装一个回调 2 //回调:启动子线程执行动作A--不阻塞--A执行完后子线程会执行动作B 3 /// <summary> 4 /// 5 /// </summary> 6 /// <param name="threadStart">多线程执行的操作</param> 7 /// <param name="actionCallback">线程完成后,回调的动作</param> 8 private void ThreadWithCallBack(ThreadStart threadStart, Action actionCallback) 9 { 10 //Thread thread = new Thread(threadStart); 11 //thread.Start(); 12 //thread.Join();//错了,因为方法被阻塞了 13 //actionCallback.Invoke(); 14 15 ThreadStart method = new ThreadStart(() => 16 { 17 threadStart.Invoke(); 18 actionCallback.Invoke(); 19 }); 20 new Thread(method).Start(); 21 } 22 23 /// <summary> 24 /// 1 异步,非阻塞的 25 /// 2 还能获取到最终计算结果 26 /// 27 /// 既要不阻塞,又要计算结果?不可能! 28 /// </summary> 29 /// <typeparam name="T"></typeparam> 30 /// <param name="func"></param> 31 /// <returns></returns> 32 private Func<T> ThreadWithReturn<T>(Func<T> func) 33 { 34 T t = default(T); 35 ThreadStart threadStart = new ThreadStart(() => 36 { 37 t = func.Invoke(); 38 }); 39 Thread thread = new Thread(threadStart); 40 thread.Start(); 41 42 return new Func<T>(() => 43 { 44 thread.Join(); 45 //thread.ThreadState 46 return t; 47 }); 48 } 49 50 51 #endregion
线程池 自己小小的理解
/// 如果某个对象创建和销毁代价比较高,同时这个对象还可以反复使用的,就需要一个池子
/// 保存多个这样的对象,需要用的时候从池子里面获取;用完之后不用销毁,放回池子;(享元模式)
/// 节约资源提升性能;此外,还能管控总数量,防止滥用;
///
/// ThreadPool的线程都是后台线程
1 #region ThreadPool线程池(概念理解) 2 3 /* 4 * 5 Thread 对线程数量没有控制 6 7 线程池 8 如果某个对象创建和销毁代价比较高,同时这个对象还可以反复使用的,就需要一个池子,保存多个这样的对象,需要用的时候从池子里面去获取用完之后不用销毁,放回池子(享元模式) 9 节约资源提升性能,此外还能管控总数量,防止滥用 10 11 ThreadPool是一个全局的是使用的单例的全局如果设置了最大线程数的话,那么整个程序都将会只有几个线程 12 13 Task --Parrallel--Async/await 全部都是采用的ThreadPool中的线程数量但是new Thread声明的线程不在ThreadPool中但是会占据线程池中的线程数量 14 15 16 */ 17 private static void ThreadPoolWithBack() 18 { 19 20 /* 21 QueueUserWorkItem(WaitCallback) 22 WaitCallback//就是一个无返回类型的委托 23 */ 24 25 //开关关闭时 26 27 /* 28 ManualResetEvent mre = new ManualResetEvent(false); 像一个开关 false关闭 true打开 29 30 mre.Reset(); //将开关关闭 mre.Set();//将开关打开 31 32 mre.WaitOne(); 数据传输的门 如果门是被关闭的话,就无法进行传输.后面的代码就无法继续执行 33 */ 34 35 { 36 ManualResetEvent mre = new ManualResetEvent(false); 37 ThreadPool.QueueUserWorkItem((x)=> { 38 Console.WriteLine($"线程Id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); 39 // mre.Set();//将开关打开 40 mre.Reset(); //将开关关闭 41 }); 42 Console.WriteLine("线程池中的委托方法已经钟"); 43 mre.WaitOne(); 44 // 如果没有将mre.set()打开下面的代码是不会执行的因为没有将mre打开 45 Console.WriteLine("线程池中的委托方法已经全部执行完毕"); 46 } 47 48 { 49 ThreadPool.SetMaxThreads(8, 8);//设置最大线程数量为workerThreads8,completionPortThreads8 50 51 ManualResetEvent mre = new ManualResetEvent(false); 52 ThreadPool.QueueUserWorkItem((x) => { 53 Console.WriteLine($"线程Id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); 54 // mre.Set();//将开关打开 55 mre.Reset(); //将开关关闭 56 }); 57 Console.WriteLine("线程池中的委托方法已经钟"); 58 mre.WaitOne(); 59 // 如果没有将mre.set()打开下面的代码是不会执行的因为没有将mre打开 60 Console.WriteLine("线程池中的委托方法已经全部执行完毕"); 61 } 62 } 63 #endregion
以上是关于Thread--线程的主要内容,如果未能解决你的问题,请参考以下文章
NDK: ant 错误 [javah] Exception in thread "main" java.lang.NullPointerException 多种解决办法(代码片段