• 多线程系列(三)之线程池


    什么是线程池?

    .NetFramework1.0时代的Thread,API功能繁多,对线程的数量是没有管控的,在.NetFramework2.0时代推出了ThreadPool,如果某个对象创建和销毁代价比较高,同时这个对象还可以反复使这些线程,就需要使用线程池,线程池可以保存多个线程对象,需要使用线程时直接从线程池里面拿,使用完之后不做释放,又放回池子(享元模式),需要用的时候再去拿。这样可以减少创建线程的开销,提升性能,此外,还可以管控线程的总数量,防止资源滥用。

    委托异步调用、Task、Parrallel、async/await的线程全部都是线程池里面的线程。直接new Thread开起的线程不受线程池的数量限制(但是会占用线程池的线程数量)。

    使用线程池开启线程

                ThreadPool.QueueUserWorkItem(o=>this.DoSomeThing("btnThreadPool_Click_1"));
                ThreadPool.QueueUserWorkItem(o => {
                    this.DoSomeThing("btnThreadPool_Click_2");
                    Console.WriteLine( o?.ToString());
                }, "wjl");

    检索和设置线程池的最大最小数目和异步IO线程的最大最小数目

    I/O线程是.NET专为访问外部资源所设置的一种线程,因为访问外部资源常常要受到外界因素的影响,为了防止让主线程受影响而长期处于阻塞状态,.NET为多个I/O操作都建立起了异步方法。

                //检索由 GetMaxThreads 返回的线程池线程的最大数目和异步IO线程的最大数目
                ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
                Console.WriteLine($"当前线程池最大数目为:{workerThreads},最大异步IO线程:{completionPortThreads}");
    
                //检索由 GetMinThreads 返回的线程池线程的最小数目和异步IO线程的最小数目
                ThreadPool.GetMinThreads(out int workerThreadsMin, out int completionPortThreadsMin);
                Console.WriteLine($"当前线程池最小数目为:{workerThreadsMin},最小异步IO线程:{completionPortThreadsMin}");
    
                ThreadPool.SetMaxThreads(8, 8);//设置的最大值,必须大于CPU核数,否则设置无效
                ThreadPool.SetMinThreads(2, 2);

    线程等待

    单个线程等待:

                    //线程等待
                    ManualResetEvent mre = new ManualResetEvent(false);
                    //ManualResetEvent是一种信号量的方式
                    //如果初始为false--关闭, mre.Set()之后变为ture,WaitOne就能通过
                    //如果初始为tue--打开, mre.Rset()之后变为false,WaitOne就只能等待
                    ThreadPool.QueueUserWorkItem(o => {
                        this.DoSomeThing("btnThreadPool_Click_3");
                        mre.Set();
                    });
                    mre.WaitOne();
                    Console.WriteLine("任务已经完成了...");

    多个线程等待:

                    ManualResetEvent[] mres = new ManualResetEvent[10];
                    for (int i = 0; i < 10; i++)
                    {
                        mres[i] = new ManualResetEvent(false);
                        int k = i;
                        ThreadPool.QueueUserWorkItem(o =>
                        {
                            this.DoSomeThing($"mres{k}");
                            ManualResetEvent mre = o as ManualResetEvent;
                            mre.Set();
                        }, mres[i]);
                    }
                    //等待所有数组中的元素都收到信号,如果是控制台程序或者winform程序,请将Main()函数上面的特性[STAThread]注释掉
                    WaitHandle.WaitAll(mres);
                    Console.WriteLine("多个任务已经完成了...");
  • 相关阅读:
    【springboot】处理【跨域】请求
    【JPA】【概念】JPA概念解析:CascadeType(各种级联操作)详解
    【JPA】关于SpringBoot使用JPA的更新操作(save方法和原生SQL方法)
    jpa @query上使用if判断
    【Jpa】动态多表if多条件联合查询,并对查询结果进行分页
    phpstorm2020.1 免注册
    uniapp实现多语言切换
    vue进页面input自动获取焦点
    vue-cli4使用less全局变量
    用js实现隐藏手机号中间四位
  • 原文地址:https://www.cnblogs.com/netlws/p/13552928.html
Copyright © 2020-2023  润新知