多线程,异步

Posted yoyo2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程,异步相关的知识,希望对你有一定的参考价值。

 

 

Task

 

线程(Thread)

线程,是操作系统能够进行运算调度的最小单位。

它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 

同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。 
一个进程可以有很多线程,每条线程并行执行不同的任务。(来自百度百科)

 

CountdownEvent countdown = new CountdownEvent(100); //表示在计数变为零时处于有信号状态的同步基元            
            Stopwatch sw = Stopwatch.StartNew();// 提供一组方法和属性,可用于准确地测量运行时间。
            for (int i = 0; i < 100; i++)
            {
                new Thread(() =>
                {
                    Console.WriteLine($"创建线程的ID为:{Thread.CurrentThread.ManagedThreadId}");
                    countdown.Signal();//减少1个信号
                }).Start();
            }
            countdown.Wait();//阻塞当前线程,直到 CountdownEvent 的信号数量变为 0
            sw.Stop();//停止测量某个时间间隔的运行时间
            Console.WriteLine($"创建100个线程执行的时间为:{sw.ElapsedMilliseconds.ToString()}");
            Console.ReadLine();

技术图片

 

运行后发现创建100个线程的时间为1149ms,并且每个线程都不同。当创建的线程数超过系统的最大线程数的话,那么系统直接over了。有没有解决的办法呢,答案当然是有的,就是线程池(ThreadPool)技术。

  通过创建线程池对象,当需要使用线程时,就去池中看有没有创建好的线程,有的话就直接将创建好的线程拿出来,线程池中没有的话,就新创建一个线程,当线程使用完后,将放回线程池中供下次使用,这样不仅可以减少创建线程消耗的时间以及消耗的内存,还能够提高线程的利用率。

 

 

线程池(ThreadPool)

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。 (来自百度百科

 

CountdownEvent countdown = new CountdownEvent(100); //表示在计数变为零时处于有信号状态的同步基元            
            Stopwatch sw = Stopwatch.StartNew();// 提供一组方法和属性,可用于准确地测量运行时间。
            for (int i = 0; i < 100; i++)
            {
                ThreadPool.QueueUserWorkItem((state) =>
                {
                    Console.WriteLine($"创建线程的ID为:{Thread.CurrentThread.ManagedThreadId}");
                    countdown.Signal();//减少1个信号
                });
            }
            countdown.Wait();//阻塞当前线程,直到 CountdownEvent 的信号数量变为 0
            sw.Stop();//停止测量某个时间间隔的运行时间
            Console.WriteLine($"创建100个线程执行的时间为:{sw.ElapsedMilliseconds.ToString()}");
            Console.ReadLine();

技术图片

从上面的运行结果我们可以发现,通过线程池去创建的线程,或者更准确点应该是去线程池获取线程比创建线程所花的时间简直是天差地别,线程的ID也是重复的,这也是通过线程池来获取线程可以提高线程的利用率。在这里需要注意的一点是通过线程池获取的线程都默认为后台线程。

 

 

参考:https://www.cnblogs.com/Opiece/p/4803836.html

 

以上是关于多线程,异步的主要内容,如果未能解决你的问题,请参考以下文章

多线程更新UI的常用方法

8异步和多线程

C# Winform 多线程异步委托进度条

多线程 Thread 线程同步 synchronized

异步任务片段背景数据

Java多线程概述及创建