5天不再惧怕多线程——第五天 线程池

转载 2012年03月21日 14:21:37
 说到多线程,不可不说线程池,C#中关于池的概念很多,今天来整理下ThreadPool的使用。

 

   是的,如果你很懒,如果你的执行任务比较短,如果你不想对线程做更精细的控制,那么把这些繁琐的东西丢给线程池吧。

 

一:ThreadPool

 好了,下面看看TheadPool下有哪些常用的方法。

1:GetMaxThreads,GetMinThreads

  首先我们肯定好奇线程池到底给我们如何控制线程数,下面就具体的看一看。

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             int workerThreads;
 6 
 7             int completePortsThreads;
 8 
 9             ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads);
10 
11             Console.WriteLine("线程池中最大的线程数{0},线程池中异步IO线程的最大数目{1}", workerThreads, completePortsThreads);
12 
13             ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads);
14 
15             Console.WriteLine("线程池中最小的线程数{0},线程池中异步IO线程的最小数目{1}", workerThreads, completePortsThreads);
16         }
17     }

 

有的同学可能就要问,我可以将1023设置为10230吗?那么就会有10230个线程帮我做事多好啊,其实不然。

①:我先前的文章也说过,线程很多的话,线程调度就越频繁,可能就会出现某个任务执行的时间比线程调度花费的时间短很多的尴尬局面。

②:我们要知道一个线程默认占用1M的堆栈空间,如果10230个线程将会占用差不多10G的内存空间,我想普通的电脑立马罢工。

 

2:SetMaxTheads,SetMinThreads

当然,默认的线程设置只是一个参考,如果我们处于性能和实际情况确实需要修改也没关系,framework也给我们提供了现成的方法。

 1  class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             int workerThreads;
 6 
 7             int completePortsThreads;
 
 8            
 9             ThreadPool.SetMaxThreads(100, 50);
10 
11             ThreadPool.SetMinThreads(20, 10);
12 
13             ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads);
14 
15             Console.WriteLine("线程池中最大的线程数{0},线程池中异步IO线程的最大数目{1}\n", workerThreads, completePortsThreads);
16 
17             ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads);
18 
19             Console.WriteLine("线程池中最小的线程数{0},线程池中异步IO线程的最小数目{1}\n", workerThreads, completePortsThreads);
20         }
21     }
 


3: QueueUserWorkItem

    需要容纳任务并执行的方法来了,该方法有一个WaitCallBack的委托,我们只需要把将要执行的任务丢给委托,CLR将会在线程池中调派空闲的

线程执行。

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
 
            ThreadPool.QueueUserWorkItem(Run1);

            Console.Read();
        }

        static void Run1(object obj)
        {
            Console.WriteLine("我是线程{0},我是线程池中的线程吗? \n回答:{1}", Thread.CurrentThread.ManagedThreadId,
                                                                           Thread.CurrentThread.IsThreadPoolThread);
        }
    }
}
 
 

   可能我们也需要像普通的Thread一样带一些参数到工作线程中,QueueUserWorkItem的第二个重载版本解决了我们的问题。

 1    class Program
 
2     {
 3         static void Main(string[] args)
 
 4         {
 5             ThreadPool.QueueUserWorkItem(Run1, "我是主线程");
 
 6 
 7             Console.Read();
 8         }
 
 9 
10         static void Run1(object obj)
11         {
12             Console.WriteLine(obj);
13         }
14     }
 


4:RegisterWaitForSingleObject

     我们知道,如果我们把要执行的任务丢给线程池后,相当于把自己的命运寄托在别人的手上。

①:我们再也不能控制线程的优先级了。

②:丢给线程池后,我们再也不能将要执行的任务取消了。

是的,给别人就要遵守别人的游戏规则,不过RegisterWaitForSingleObject提供了一些简单的线程间交互,因为该方法的第一个参数是

WaitHandle,在VS对象浏览器中,我们发现EventWaitHandle继承了WaitHandle,而ManualResetEvent和AutoResetEvent都继承于

EventWaitHandle,也就是说我们可以在RegisterWaitForSingleObject溶于信号量的概念。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             AutoResetEvent ar = new AutoResetEvent(false);
 6 
 7             ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, Timeout.Infinite, false);
 8 
 9             Console.WriteLine("时间:{0} 工作线程请注意,您需要等待5s才能执行。\n", DateTime.Now);
10 
11             //5s
12             Thread.Sleep(5000);
13 
14             ar.Set();
15 
16             Console.WriteLine("时间:{0} 工作线程已执行。\n", DateTime.Now);
17 
18             Console.Read();
19         }
20 
21         static void Run1(object obj, bool sign)
22         {
23             Console.WriteLine("当前时间:{0}  我是线程{1}\n", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
24         }
 
25     }
 

 

我们知道在Threading下面有一个Timer计时器,当定期触发任务的时候都是由线程池提供并给予执行,那么这里我们溶于信号量的概念以后同样

可以实现计时器的功能。

 1  class Program
 
2     {
 3         static void Main(string[] args)
 4         {
 5             AutoResetEvent ar = new AutoResetEvent(false);
 6 
 7             //参数2000:其实就是WaitOne(2000),采取超时机制
 8             ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, 2000, false);
 9 
10             Console.Read();
11         }
12 
13         static void Run1(object obj, bool sign)
14         {
15             Console.WriteLine("当前时间:{0}  我是线程{1}\n", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
16         }
17     }
18 }
 

 

有时候,跑着跑着我们需要在某个时刻停止它,没关系,RegisterWaitForSingleObject返回一个RegisteredWaitHandle类,那么我们就通过

RegisteredWaitHandle来动态的控制,比如说停止计数器的运行。

 1   class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             RegisteredWaitHandle handle = null;
 
 6 
 7             AutoResetEvent ar = new AutoResetEvent(false);
 8 
 
 9             handle = ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, 2000, false);
10 
11             //10s后停止
12             Thread.Sleep(10000);
13 
14             handle.Unregister(ar);
15 
16             Console.WriteLine("小子,主线程要干掉你了。");
17 
18             Console.Read();
19         }
20 
 
21         static void Run1(object obj, bool sign)
22         {
23             Console.WriteLine("当前时间:{0}  我是线程{1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
24         }
25     }

 

5天不再惧怕多线程——第五天 线程池

作者:一线码农 转自:http://www.cnblogs.com/huangxincheng/archive/2012/03/18/2405039.html
  • whw8007
  • whw8007
  • 2014年10月28日 11:24
  • 624

5天不再惧怕多线程——第五天 线程池

5天不再惧怕多线程——第五天 线程池     说到多线程,不可不说线程池,C#中关于池的概念很多,今天来整理下ThreadPool的使用。      是的,如果你很懒,如果你的执...

5天不再惧怕多线程——第一天 尝试Thread

原本准备在mongodb之后写一个lucene.net系列,不过这几天用到多线程时才发现自己对多线程的了解少之又少,仅仅停留在lock上面, 故这几天看了下线程参考手册结合自己的心得整理一下放在博客...

5天不再惧怕多线程——第一天 尝试Thread

原本准备在mongodb之后写一个lucene.net系列,不过这几天用到多线程时才发现自己对多线程的了解少之又少,仅仅停留在lock上面, 故这几天看了下线程参考手册结合自己的心得整理一下放在博客...

5天不再惧怕多线程——第四天 信号量

5天不再惧怕多线程——第四天 信号量     今天整理“信号量”的相关知识,其实想想也蛮有趣的,锁,互斥,信号量都可以实现线程同步,在framework里面主要有三种。 :Manu...

5天不再惧怕多线程——第二天 锁机制

当多个线程在并发的时候,难免会碰到相互冲突的事情,比如最经典的ATM机的问题,并发不可怕,可怕的是我们没有能力控制。 线程以我的理解可以分为三种 ① 锁。 ② 互斥。 ③ 信号。   好,这...

5天不再惧怕多线程——第四天 信号量

今天整理“信号量”的相关知识,其实想想也蛮有趣的,锁,互斥,信号量都可以实现线程同步,在framework里面主要有三种。 :ManualResetEvent :AutoResetEvent :...

5天不再惧怕多线程——第一天 尝试Thread

作者: 转自:
  • whw8007
  • whw8007
  • 2014年10月28日 11:11
  • 1859

5天不再惧怕多线程——第四天 信号量

今天整理“信号量”的相关知识,其实想想也蛮有趣的,锁,互斥,信号量都可以实现线程同步,在framework里面主要有三种。 :ManualResetEvent :AutoResetEvent :...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:5天不再惧怕多线程——第五天 线程池
举报原因:
原因补充:

(最多只允许输入30个字)