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--线程的主要内容,如果未能解决你的问题,请参考以下文章

java线程

Java中通过Runnable与Thread创建线程的区别

python threading超线程使用简单范例的代码

C# Thread开启线程的几种方式

NDK: ant 错误 [javah] Exception in thread "main" java.lang.NullPointerException 多种解决办法(代码片段

使用 std::thread 函数 C++11 将指针作为参数传递