如何理解深入浅出多线程系列之三:线程池的原理与应用?
- 内容介绍
- 文章标签
- 相关推荐
本文共计811个文字,预计阅读时间需要4分钟。
线程池:每个线程默认分配1MB内存,在C++中直接输出:线程池:每个线程默认分配1MB内存。
线程池:
每一个线程默认会被分配1MB的内存,在C#中,这些都是实打实的分配的,当一个线程启动的时候,为了分配临时堆栈大约需要花费几百微秒的时间。
线程池通过循环利用线程可以让你更高效的利用线程。
线程池就像外包的劳务队一样,有任务给他们,他们会管理劳务工的一切,你不需要去花时间去找单个劳务工,然后完成任务就解雇她,
对劳务队而言,劳务工完成了你的这个任务,还是会回到自己的团队中的,劳务工的管理也不需要你去负责,因为这由劳务队处理了,
如果任务太多了,劳务队会自己招一个劳务工,如果还不够就继续招,但是如果任务比较少,而劳务工又比较多的话,对不起,劳务队的管理人员就会解雇一部分劳务工了。
有很多方法可以进入线程池:
- 借助Task Parallel Library(framework 4.0)
- 调用ThreadPool.QueueUserWorkItem
- 借助异步委托。
- 借助BackgroundWorker.。
下面的一些构造间接的使用了线程池:
- WCF,Remoting,Asp.net, asmx web services应用程序。
- System.Timers.Timer 和 System.Threading.Timer.
- framework的一些异步方法,例如WebClient 类,和大部分BeginXXX方法。
- PLINQ
使用线程池的一些问题:
- 不可以设置一个线程池线程的名字。
- 线程池线程全部都是后台线程。
- 阻塞一个线程池线程可能会触发创建一个新线程,除非你调用ThreadPool.SetMinThreads方法。
通过Thread.CurrentThread.IsThreadPoolThread属性可以查询一个线程是否是线程池线程。
实战ThreadPool
1:通过Task使用线程池:
publicstaticvoidMainThread(){
Task<string>task=Task.Factory.StartNew<string>
(()=>DownloadString("www.google.com"));
//DoSomething
stringresult=task.Result;
}
staticstringDownloadString(stringuri)
{
using(varwc=newSystem.Net.WebClient())
returnwc.DownloadString(uri);
}
当查询task.Result的时候线程阻塞,等待task返回Result。
2:通过ThreadPool.QueueUserWorkItem
publicstaticvoidMainThread(){
ThreadPool.QueueUserWorkItem(Go);
ThreadPool.QueueUserWorkItem(Go,123);
Console.ReadLine();
}
staticvoidGo(objectdata)
{
Console.WriteLine("Hellofromthethreadpool!"+data);
}
Output:
Hello from the thread pool!
Hello from the thread pool! 123
3:借助委托的BeginXXX方法:
publicstaticvoidMainThread(){
Func<string,int>method=Work;
method.BeginInvoke("test",Done,method);
}
staticintWork(strings){returns.Length;}
staticvoidDone(IAsyncResultcookie)
{
vartarget=(Func<string,int>)cookie.AsyncState;
intresult=target.EndInvoke(cookie);
Console.WriteLine("Stringlengthis:"+result);
}
在这里将method当作参数进行传递后,在cookie的AsyncState中就可以使用传递的method了,
因为cookie.AsyncState类型是object,所以需要进行转换,然后调用EndInvoke方法来获取结果。
参考资料:
www.albahari.com/threading/
CLR Via C# 3.0
本文共计811个文字,预计阅读时间需要4分钟。
线程池:每个线程默认分配1MB内存,在C++中直接输出:线程池:每个线程默认分配1MB内存。
线程池:
每一个线程默认会被分配1MB的内存,在C#中,这些都是实打实的分配的,当一个线程启动的时候,为了分配临时堆栈大约需要花费几百微秒的时间。
线程池通过循环利用线程可以让你更高效的利用线程。
线程池就像外包的劳务队一样,有任务给他们,他们会管理劳务工的一切,你不需要去花时间去找单个劳务工,然后完成任务就解雇她,
对劳务队而言,劳务工完成了你的这个任务,还是会回到自己的团队中的,劳务工的管理也不需要你去负责,因为这由劳务队处理了,
如果任务太多了,劳务队会自己招一个劳务工,如果还不够就继续招,但是如果任务比较少,而劳务工又比较多的话,对不起,劳务队的管理人员就会解雇一部分劳务工了。
有很多方法可以进入线程池:
- 借助Task Parallel Library(framework 4.0)
- 调用ThreadPool.QueueUserWorkItem
- 借助异步委托。
- 借助BackgroundWorker.。
下面的一些构造间接的使用了线程池:
- WCF,Remoting,Asp.net, asmx web services应用程序。
- System.Timers.Timer 和 System.Threading.Timer.
- framework的一些异步方法,例如WebClient 类,和大部分BeginXXX方法。
- PLINQ
使用线程池的一些问题:
- 不可以设置一个线程池线程的名字。
- 线程池线程全部都是后台线程。
- 阻塞一个线程池线程可能会触发创建一个新线程,除非你调用ThreadPool.SetMinThreads方法。
通过Thread.CurrentThread.IsThreadPoolThread属性可以查询一个线程是否是线程池线程。
实战ThreadPool
1:通过Task使用线程池:
publicstaticvoidMainThread(){
Task<string>task=Task.Factory.StartNew<string>
(()=>DownloadString("www.google.com"));
//DoSomething
stringresult=task.Result;
}
staticstringDownloadString(stringuri)
{
using(varwc=newSystem.Net.WebClient())
returnwc.DownloadString(uri);
}
当查询task.Result的时候线程阻塞,等待task返回Result。
2:通过ThreadPool.QueueUserWorkItem
publicstaticvoidMainThread(){
ThreadPool.QueueUserWorkItem(Go);
ThreadPool.QueueUserWorkItem(Go,123);
Console.ReadLine();
}
staticvoidGo(objectdata)
{
Console.WriteLine("Hellofromthethreadpool!"+data);
}
Output:
Hello from the thread pool!
Hello from the thread pool! 123
3:借助委托的BeginXXX方法:
publicstaticvoidMainThread(){
Func<string,int>method=Work;
method.BeginInvoke("test",Done,method);
}
staticintWork(strings){returns.Length;}
staticvoidDone(IAsyncResultcookie)
{
vartarget=(Func<string,int>)cookie.AsyncState;
intresult=target.EndInvoke(cookie);
Console.WriteLine("Stringlengthis:"+result);
}
在这里将method当作参数进行传递后,在cookie的AsyncState中就可以使用传递的method了,
因为cookie.AsyncState类型是object,所以需要进行转换,然后调用EndInvoke方法来获取结果。
参考资料:
www.albahari.com/threading/
CLR Via C# 3.0

