zoukankan      html  css  js  c++  java
  • 线程池与并行度

    展示线程池如何工作于大量的异步操作,以及它与创建大量单独的线程的方式有什么不同。

    大量创建线程(消耗内存、CPU系统资源,请观察)

    使用线程池:执行的时间更长,但对系统资源消耗要小的多

    using System;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Diagnostics;
    
    namespace Test
    {
        class Program
        {
            private static void UseThreads(int count)
            {
                //通过CountdownEvent可以在主线程中线程池中的任务运行,主线程要等待线程池中的任务完成之后才能继续
                using (var countdown = new CountdownEvent(count))//这里给CountdownEvent指定计数为500
                {
                    for (int i = 0; i < count; i++)
                    {
                        //使用普通线程
                        var t1 = new Thread(() =>
                        {
                            //CurrentThreadInfo("UseThreads()的");
    
                            Thread.Sleep(TimeSpan.FromMilliseconds(100));
                            countdown.Signal();//每次循环CountdownEvent在这里计数减1,一直减少到0
                        });
                        t1.Start();
                    }
    
                    countdown.Wait();//主线程一开始在这里停止并等待,CountdownEvent计数减少到0的时候,这里主线程开始执行
                }
            }
    
            private static void UseThreadPool(int count)
            {
                using (var countdown = new CountdownEvent(count))
                {
                    for (int i = 0; i < count; i++)
                    {
                        //使用线程池
                        ThreadPool.QueueUserWorkItem(_ =>
                        {
                            //CurrentThreadInfo("UseThreadPool()的");
    
                            Thread.Sleep(TimeSpan.FromMilliseconds(100));
                            countdown.Signal();
                        });
                    }
    
                    countdown.Wait();
                }
            }
    
            /// <summary>
            /// 向线程池放入异步操作
            /// </summary>
            static void Main()
            {
                //CurrentThreadInfo("主线程Main()的");
    
                int count = 500;
    
    
                CodeTimer.Initialize();
    
                int iteration = 2;
                CodeTimer.Time("UseThreads", iteration, () =>
                {
                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    UseThreads(count);
                    sw.Stop();
                    Console.WriteLine("使用简单线程耗时:{0} - 计数:{1}", sw.ElapsedMilliseconds, sw.ElapsedTicks);
                });
    
                CodeTimer.Time("UseThreadPool", iteration, () =>
                {
    
                    Stopwatch sw2 = new Stopwatch();
                    sw2.Start();
                    UseThreadPool(count);
                    sw2.Stop();
                    Console.WriteLine("使用线程池中耗时:{0} - 计数:{1}", sw2.ElapsedMilliseconds, sw2.ElapsedTicks);
                });
    
    
                Console.WriteLine("执行完成");
                Console.ReadLine();
            }
    
    
    
            /// <summary>
            /// 当前线程信息
            /// </summary>
            private static void CurrentThreadInfo(string name)
            {
                StringBuilder builder = new StringBuilder();
                builder.AppendLine("");
                builder.AppendLine(String.Format("{0}线程Id:		{1}", name, Thread.CurrentThread.ManagedThreadId));
                builder.AppendLine(String.Format("{0}是否使用线程池:	{1}", name, Thread.CurrentThread.IsThreadPoolThread));
                builder.AppendLine(String.Format("{0}是否后台线程:	{1}", name, Thread.CurrentThread.IsBackground));
                builder.AppendLine(String.Format("{0}线程状态:		{1}", name, Thread.CurrentThread.ThreadState.ToString()));
                builder.AppendLine(String.Format("{0}当前时间:		{1}", name, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                builder.AppendLine("");
    
                Console.WriteLine(builder.ToString());
            }
        }
    }

    工作原理:

    使用普通线程

    当主程序启动时,创建了很多不同的线程,每个线程都运行一个操作。该操作打印出线程ID并阻塞线程100毫秒。结果我们创建了500个线程,全部并行运行这些操作。虽然在我的机器上的总耗时是300毫秒,但是所有线程消耗了大量的操作系统资源

    使用线程池

    然后我们使用了执行同样的任务,只不过部位每个操作创建一个线程,儿将他们放入到线程池中。然后线程池开始执行这些操作。线程池在快结束时创建更多的线程,但是仍然花费了更多的时间,在我机器上是12秒。我们为操作系统节省了内存和线程数,但是为此付出了更长的执行时间。

  • 相关阅读:
    HPU 1007: 严格递增连续子段(贪心)
    Codeforces Round #224 (Div. 2) A. Ksenia and Pan Scales
    Codeforces Round #224 (Div. 2) A. Ksenia and Pan Scales
    51Nod 1058: N的阶乘的长度(斯特林公式)
    51Nod 1090: 3个数和为0
    CSU 1112: 机器人的指令
    有关刷题时的多组输入问题
    HDU 1060:Leftmost Digit
    《算法导论》— Chapter 6 堆排序
    《算法导论》— Chapter 9 中位数和顺序统计学
  • 原文地址:https://www.cnblogs.com/gougou1981/p/12443839.html
Copyright © 2011-2022 走看看