线程:是Windows任务调度的最小单位。线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数,在一个应用程序中,常常需要使用多个线程来处理不同的事情,这样可以提高程序的运行效率,也不会使主界面出现无响应的情况。在这里主要介绍线程(Thread)、线程池(ThreadPool)两种不同创建线程的区别
在通常的情况下,当我们需要开启一个新的线程时,我们直接通过Thread(继承自 System.Threading;)去创建一个新的线程,这样做有一个好处就是我们可以拿到这个新创建的线程,并且可以对这个线程去做一些相关的操作。但是通过创建一个新的线程会比较消耗资源,我们都知道,操作系统的资源是有限的,当用户访问的多了,需要开启的线程也跟着多了,当开启的线程超过系统的最大线程数时,系统就容易出现崩溃。下面我们来看一下创建100个线程所需要的时间
for (int i = 0; i < 100; i++)//创建100个线程 { new Thread(() => { Console.WriteLine("创建线程的ID为:"+Thread.CurrentThread.ManagedThreadId); }).Start(); } sw.Stop(); Console.WriteLine("创建100个线程执行的时间为:"+sw.ElapsedMilliseconds.ToString());
运行后我们发现创建100个线程的时间为489ms,并且每个线程都不同。当创建的线程数超过系统的最大线程数的话,那么系统直接over了。有没有解决的办法呢,答案当然是有的,就是线程池(ThreadPool)技术。
通过创建线程池对象,当需要使用线程时,就去池中看有没有创建好的线程,有的话就直接将创建好的线程拿出来,线程池中没有的话,就新创建一个线程,当线程使用完后,将放回线程池中供下次使用,这样不仅可以减少创建线程消耗的时间以及消耗的内存,还能够提高线程的利用率。
for (int i = 0; i < 100; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback((s) => { Console.WriteLine("创建线程的ID为:" + Thread.CurrentThread.ManagedThreadId); })); }
从上面的运行结果我们可以发现,通过线程池去创建的线程,或者更准确点应该是去线程池获取线程比创建线程所花的时间简直是天差地别,线程的ID也是重复的,这也是通过线程池来获取线程可以提高线程的利用率。在这里需要注意的一点是通过线程池获取的线程都默认为后台线程
最后,简单的介绍一下Task工作任务项,Task为.net4.0引入的新的使用线程池技术,微软的MSDN上这样介绍:Task 类的表示的单个操作不会返回一个值,通常以异步方式执行。 Task 对象是一种的中心思想 基于任务的异步编程模式 首次引入.NET Framework 4 中。
在通过工厂开启的新的线程池工作任务项,会直接执行,而通过自己创建的新飞工作任务项,需要自己手动去开启执行
//使用工厂创建一个工作任务项,并执行了 Task t1 = Task.Factory.StartNew(() => { //执行代码 }); //Task t1 = new Task(() => // { // Thread.Sleep(2000); // Console.WriteLine("当前的线程是:"+Thread.CurrentThread.ManagedThreadId); // }); //t1.Start();//需要手动启动去执行
总结:在实际的开发中,当不需要对线程进行操作的话,不要手动去创建线程,尽量的使用线程池技术去创建开启一个线程,可以提高线程的使用效率,使用线程池技术也可以提高应用程序的效率。