• 异步多线程(三)ThreadPool


    概念

    线程池诞生的原因: Thread 过于强大,无法管控线程数量。

    如果某个对象创建和销毁代价比较高,同时这个对象还可以反复使用的,就需要一个池子

    保存多个这样的对象,需要用的时候从池子里面获取;用完之后不用销毁,放回池子;(享元模式)

    节约资源提升性能;此外,还能管控总数量,防止滥用;

    线程池启动线程的方法

    方法一

    ThreadPool.QueueUserWorkItem(

    o=> this.DoSomethingLong("btnThreadPool_Click1"));

    方法二

    ThreadPool.QueueUserWorkItem(

    o=> this.DoSomethingLong("btnThreadPool_Click2"), "嘿嘿");

    获取线程池线程数量

      获取线程池最大线程数量

    ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);

      获取线程池最小线程数量

    ThreadPool.GetMinThreads(out intworkerThreadsMin, out int completionPortThreadsMin);

    设置线程池最大线程数量

    ThreadPool.SetMaxThreads(8, 8);//设置的最大值,必须大于CPU核数,否则设置无效

    设置线程池最小线程数量

    ThreadPool.SetMinThreads(2, 2);

    注意:这里设置的线程池线程数量是全局的,在设置的时候请一定小心处理

    例如你设置的最大线程是8,那么在你的整个项目,只能并发运行8个线程。

    线程池设置线程等待

      ManualResetEvent mre = new ManualResetEvent(false);

      //false---关闭---Set打开---true---WaitOne就能通过

      //true---打开--ReSet关闭---false--WaitOne就只能等待

      ThreadPool.QueueUserWorkItem(o =>

      {

          this.DoSomethingLong("btnThreadPool_Click1");

          mre.Set();

      });

      mre.WaitOne();

      Console.WriteLine("任务已经完成了。。。");

    以下是完整的代码示例

            //ThreadPool 
            /// <summary>
            /// 
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void button1_Click(object sender, EventArgs e)
            {
    
    
                #region 启动线程池
                //启动ThreadPool方式一
                ThreadPool.QueueUserWorkItem(s => Console.WriteLine("button1_Click"));
                //启动ThreadPool方式二
                ThreadPool.QueueUserWorkItem(s => Console.WriteLine("button1_Click"), "嘿嘿");
                #endregion
    
                #region 获取线程池线程最大最小值
                ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
                Console.WriteLine($"当前计算机最大workerThreads是{workerThreads},最大completionPortThreads是{completionPortThreads}");
    
                ThreadPool.GetMinThreads(out int workerThreadsMini, out int completionPortThreadsMini);
                Console.WriteLine($"当前计算机最小workerThreadsMini是{workerThreadsMini},最小completionPortThreadsMini是{completionPortThreadsMini}");
                #endregion
    
                #region 设置线程池线程数(最大最小),设置的线程池数量是进程全局的,
                //委托异步调用--Task--Parrallel--async/await 全部都是线程池的线程
                //如果设置的线程数量最大值小于当前计算机的最小值,则不生效。
                ThreadPool.SetMaxThreads(8, 8);
                ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
                Console.WriteLine($"当前计算机最大workerThreads是{workerThreads},最大completionPortThreads是{completionPortThreads}");
    
                ThreadPool.SetMinThreads(1, 1);
                ThreadPool.GetMinThreads(out int workerThreadsMini, out int completionPortThreadsMini);
                Console.WriteLine($"当前计算机最小workerThreadsMini是{workerThreadsMini},最小completionPortThreadsMini是{completionPortThreadsMini}");
                #endregion
    
    
                #region 设置线程池线程等待
                ManualResetEvent manualReset = new ManualResetEvent(false);
                ////false---关闭---Set打开---true---WaitOne就能通过
                ////true---打开--ReSet关闭---false--WaitOne就只能等待
                ThreadPool.QueueUserWorkItem(s =>
                {
                    this.DoSomethingLong("button1_Click");
                    manualReset.Set();
                });
                manualReset.WaitOne();
                Console.WriteLine("等待之后做的事情");
    
                #endregion
    
            }
            #region Private Method
            /// <summary>
            /// 一个比较耗时耗资源的私有方法
            /// </summary>
            /// <param name="name"></param>
            private void DoSomethingLong(string name)
            {
                Console.WriteLine($"****************DoSomethingLong Start  {name} " +
                    $" {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +
                    $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
                long lResult = 0;
                for (int i = 0; i < 1_000_000_000; i++)
                {
                    lResult += i;
                }
                //Thread.Sleep(2000);
    
                Console.WriteLine($"****************DoSomethingLong   End  {name} " +
                    $" {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +
                    $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} " +
                    $"{lResult}***************");
            }
            #endregion
  • 相关阅读:
    剑指offer-用两个栈实现队列
    Java数组判空的正确打开方式
    浏览器输入URL后后的过程
    HTTP状态码
    HTTP和HTTPS
    北京好未来公司linux面试题
    三剑客 -- sed
    三剑客 -- grep
    shell脚本
    自动化 -- expect
  • 原文地址:https://www.cnblogs.com/JohnTang/p/10991807.html
Copyright © 2020-2023  润新知