多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比
Thread.Start(),ThreadPool.QueueUserWorkItem都是在实现多线程并行编程时常用的方法。两种方式有何异同点,而又该如何取舍?
写一个Demo,分别用两种方式实现。观察各自的现象。
一个WorkMan class,其内的method doSomething()是每次异步线程调用的方法。该方法只是随机的让线程休眠一段时间。

public void doSomething()
{
OnBegin(new EventArgs()); // someone does something here
var r = new Random();
int sleepTime = r.Next(3000, 180000);
Thread.Sleep(900000); OnCompleted(new EventArgs());
} doSomething

Thread.Start()方式实现

workThreads = new Thread[NUMBER_OF_THREADS]; for (var i = 0; i < NUMBER_OF_THREADS; i++)
{
arrWorkMen[i] = new WorkMan() {
WorkStarted = true,
InstanceID = startThreadNumber
}; arrWorkMen[i].BeginHandler += HandleTaskBegin;
arrWorkMen[i].CompletedHandler += HandleTaskCompleted; // create a thread and attach to the object
var st = new ThreadStart(arrWorkMen[i].doSomething);
workThreads[i] = new Thread(st); startThreadNumber++;
} for (var i = 0; i < NUMBER_OF_THREADS; i++)
{
Thread.Sleep(2000);
workThreads[i].Start();
} Thread.Start()

ThreadPool.QueueUserWorkItem方式实现

for (var i = 0; i < NUMBER_OF_THREADS; i++)
{
arrWorkMen[i] = new WorkMan()
{
WorkStarted = true,
InstanceID = startThreadNumber
}; arrWorkMen[i].BeginHandler += HandleTaskBegin;
arrWorkMen[i].CompletedHandler += HandleTaskCompleted; startThreadNumber++;
} for (var i = 0; i < NUMBER_OF_THREADS; i++)
{
Thread.Sleep(2000);
ThreadPool.QueueUserWorkItem(o => arrWorkMen[i].doSomething());
} ThreadPool.QueueUserWorkItem

观察两种方式下,线程创建和回收的情况。
同样的场景,每2秒钟发起一新的线程,且每一线程均休眠2分钟。Thread.Start()实现下,线程一路最高飙升到71个,然后随着2分钟后休眠线程的结束,线程个数始终在70、71之间徘徊。而ThreadPool.QueueUserWorkItem的实现下,线程个数到达最高73后,始终在72、73之间徘徊。

总体来说,做同样的事情。ThreadPool方式产生的线程数略高于Thread.Start()。Thread.Start()产生的线程在完成任务后,很快被系统所回收。而ThreadPool(线程池)方式下,线程在完成工作后会被保留一段时间以备resue。所以,当需求需要大量线程并发工作的时候,不建议使用ThreadPool方式,因为它会保持很多额外的线程。
此处摘录一段来自网络的参考:
As for the ThreadPool, it is designed to use as few threads as possible while also keeping the CPU busy. Ideally, the number of busy threads is equal to the number of CPU cores. However, if the pool detects that its threads are currently not using the CPU (sleeping, or waiting for another thread), it starts up more threads (at a rate of 1/second, up to some maximum) to keep the CPU busy.
多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比的更多相关文章
- Java值创建线程的两种方式对比
在Java中创建线程的方式有两种,第一种是直接继承Thead类,另一种是实现Runable接口.那么这两种方式孰优孰劣呢? 采用继承Thead类实现多线程: 优势:编写简单,如果需要访问当前线程,只需 ...
- C# 读取Excel到DataTable两种方式对比
方式一 OLEDB读取 数据库引擎 优点:读取速度快,依据sheet排序读取 缺点:对于Excel版本依赖强,无法读取指定sheet 错误提示:本地计算机未指定 Microsoft.ACE.OLEDB ...
- python格式化输出的两种方式对比
1.%符号方法和format()函数方法 2.对比: 1 print('我今年%d岁' %22.125) 2 print('我今年{0:f}'.format(22.125)) 3 #报错 4 #槽中类 ...
- Java实现线程的两种方式?Thread类实现了Runnable接口吗?
Thread类实现了Runnable接口吗? 我们看看源码中对与Thread类的部分声明 public class Thread implements Runnable { /* Make sure ...
- 创建线程的两种方式比较Thread VS Runnable
1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 public class MyThread extends Thread{ @Override public vo ...
- Java实现多线程的两种方式
实现多线程的两种方式: 方式1: 继承Thread类 A: 自定义MyThread类继承Thread类 B: 在MyThread类中重写run() C: 创建MyThread类的对象 D: 启动线程对 ...
- 创建线程的两种方式:继承Thread类和实现Runnable接口
第一种方式:继承Thread类 步骤:1.定义类继承Thread 2.覆写Threa类的run方法. 自定义代码放在run方法中,让线程运行 3.调用线程的star方法, 该线程有两个作用:启动线程, ...
- Java中实现多线程的两种方式之间的区别
Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...
- Android 应用开发 之通过AsyncTask与ThreadPool(线程池)两种方式异步加载大量数据的分析与对比--转载
在加载大量数据的时候,经常会用到异步加载,所谓异步加载,就是把耗时的工作放到子线程里执行,当数据加载完毕的时候再到主线程进行UI刷新.在数据量非常大的情况下,我们通常会使用两种技术来进行异步加载,一 ...
随机推荐
- rman checksyntax和解决RMAN-01009: syntax error: found "dot"
在日常清归档时候执行脚本报错 RMAN-00552: syntax error in command line argumentsRMAN-01009: syntax error: found &qu ...
- vue项目中 如何让外部引入的js模块 的this值 指向vue实例
当前是vue项目,想在tool.js(工具模块)中封装一个跳转页面的方法, goToUrl(name,query){ if(query){ if(query.addressCode){ vueObje ...
- es的timeout机制
GET /_search?timeout=10ms默认情况下,es的timeout机制是关闭的.比如,如果你的搜索特别慢,每个shard都要花好几分钟才能查询出来所有的数据,那么你的搜索请求也会等待好 ...
- thinkphp无法安装提示修改mysql配置
在安装以thinkphp为框架的系统时数据库连接错误,提示修改sql-mode或sql_mode为NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION.那我们就顺着提示 ...
- 关于ios下字体描边的一个细节
转载请注明,来自:http://blog.csdn.net/skyman_2001 CGContextSetTextDrawingMode(context, kCGTextStroke); ...
- Got timeout reading communication packets解决方法
Got timeout reading communication packets解决方法 http://www.th7.cn/db/mysql/201702/225243.shtml [Note] ...
- dxCameraControl控件(拍照)
拍照演示 主要属性设置 Active:True DeviceIndex:设备号,默认为0 其他方法 procedure Capture; //捕获 procedure Pause; //暂停 proc ...
- 谷歌浏览器安装octotree插件
Octotree Chrome安装与使用方法 Octotree Chrome作用: 主要使你在github查看项目时可以清晰明了的看到项目的结构以及具体代码,使下载代码更具有目的性,减少不必要代码的下 ...
- ASP.NET学习笔记(1)
1.ASP.Net简介 A.ASP.Net动态网页技术.在服务器端运行.Net代码,动态生成HTML.在浏览器可以使用JavaScript.Dom完成前台工作.如存储数据.访问数据库.业务逻辑运算等可 ...
- react 首屏加载优化
react 首屏加载优化,原本是在入口HTML文件中加载loading动画,但是部署在测试环境上的时候一直无法显示loading的部分,也是奇怪了,我们测试环境的部署一直跟本地的都不太一样,内外网的转 ...