C# ThreadPool 线程池

Thread与ThreadPool

Thread: .NetFramework1.0  对线程对象的一个封装   

Thread方法很多很强大,但是太过强大,而且没有限制 功能繁多,反而用不好--就像给4岁小孩一把热武器,反而会造成更大的伤害 对线程数量是没有管控的

ThreadPool:.NetFramework2.0 线程池

如果某个对象创建和销毁代价比较高,同时这个对象还可以反复使用的,就需要一个池子
保存多个这样的对象,需要用的时候从池子里面获取;用完之后不用销毁,放回池子;(享元模式)
节约资源提升性能;此外,还能管控总数量,防止滥用;

ThreadPool的线程都是后台线程

常用方法

1、GetMaxThreads(Int32, Int32)   检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用,获取当前线程池中辅助线程的最大数目、线程池中异步 I/O 线程的最大数目

2、GetMinThreads(Int32, Int32)    发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量

3、SetMaxThreads(Int32, Int32)    设置可以同时处于活动状态的线程池的请求数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用

4、SetMinThreads(Int32, Int32)     发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量

 1             {
 2                 ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
 3                 Console.WriteLine($"当前电脑最大workerThreads={workerThreads} 最大completionPortThreads={completionPortThreads}");
 4 
 5                 ThreadPool.GetMinThreads(out int workerThreadsMin, out int completionPortThreadsMin);
 6                 Console.WriteLine($"当前电脑最小workerThreads={workerThreadsMin} 最大completionPortThreads={completionPortThreadsMin}");
 7 
 8                 //设置的线程池数量是进程全局的,
 9                 //委托异步调用--Task--Parrallel--async/await 全部都是线程池的线程
10                 //直接new Thread不受这个数量限制的(但是会占用线程池的线程数量)
11                 ThreadPool.SetMaxThreads(8, 8);//设置的最大值,必须大于CPU核数,否则设置无效
12                 ThreadPool.SetMinThreads(2, 2);
13                 Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&设置最大最小&&&&&&&&&&&&&&&&&&&&&&&&&&&");
14 
15                 ThreadPool.GetMaxThreads(out int workerThreads1, out int completionPortThreads1);
16                 Console.WriteLine($"当前电脑最大workerThreads={workerThreads1} 最大completionPortThreads={completionPortThreads1}");
17 
18                 ThreadPool.GetMinThreads(out int workerThreadsMin1, out int completionPortThreadsMin1);
19                 Console.WriteLine($"当前电脑最大workerThreads={workerThreadsMin1} 最大completionPortThreads={completionPortThreadsMin1}");
20             }
View Code

5、QueueUserWorkItem(WaitCallback)、QueueUserWorkItem(WaitCallback, Object)

WaitCallback 是 带一个object类型参数的委托

 1             {
 2                 ThreadPool.QueueUserWorkItem(o => DoSomeThing(), new object());
 3                 ThreadPool.QueueUserWorkItem(NoReturnWithParamater,123);
 4             }
 5         public static void DoSomeThing()
 6         {
 7             Console.WriteLine("********DoSomeThing Start ManagedThreadId:{0} {1}********", Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
 8 
 9             long sum = 0;
10             for (int i = 0; i < 1000000; i++)
11             {
12                 sum += i;
13             }
14             //Thread.Sleep(2000);
15             Console.WriteLine("********DoSomeThing End   ManagedThreadId:{0} {1}********", Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
16         }
17         public static void NoReturnWithParamater(object obj)
18         {
19             Console.WriteLine("********NoReturnWithParamater Paramater:{2}  ManagedThreadId:{0} {1}********", Thread.CurrentThread.ManagedThreadId.ToString("00"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), obj);
20         }
View Code

线程等待

 1             {
 2                 ////等待
 3                 ManualResetEvent mre = new ManualResetEvent(false);
 4                 //false---关闭---Set打开---true---WaitOne就能通过
 5                 //true---打开--ReSet关闭---false--WaitOne就只能等待
 6                 ThreadPool.QueueUserWorkItem(o =>
 7                 {
 8                     DoSomeThing();
 9                     mre.Set();
10 
11                 });
12                 Console.WriteLine("Do Something else...");
13                 Console.WriteLine("Do Something else...");
14                 Console.WriteLine("Do Something else...");
15 
16                 mre.WaitOne();
17                 Console.WriteLine("任务已经完成了。。。");
18             }
View Code
 1             {
 2                 //不要阻塞线程池里面的线程
 3                 ThreadPool.SetMaxThreads(12, 12);
 4                 ManualResetEvent mre = new ManualResetEvent(false);
 5                 for (int i = 0; i < 10; i++)
 6                 {
 7                     int k = i;
 8                     ThreadPool.QueueUserWorkItem(t =>
 9                     {
10                         Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId.ToString("00")} show {k}");
11                         if (k == 9)
12                         {
13                             mre.Set();
14                         }
15                         else
16                         {
17                             mre.WaitOne();
18                         }
19                     });
20                 }
21                 if (mre.WaitOne())
22                 {
23                     Console.WriteLine("任务全部执行成功!");
24                 }
25                 Console.WriteLine("end");
26             }
View Code

执行上面代码 当线程池最大线程数大于程序需要的线程数,程序正常执行,取消注释或当线程池最大线程数少于程序需要的线程数,程序无法正常执行

微软文档:

ThreadPool:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.threadpool?view=netframework-4.8

ManualResetEvent:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.manualresetevent?view=netframework-4.8

WaitHandle:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.waithandle?view=netframework-4.8

猜你喜欢

转载自www.cnblogs.com/Dewumu/p/11814036.html