多线程实现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刷新.在数据量非常大的情况下,我们通常会使用两种技术来进行异步加载,一 ...
随机推荐
- 《linux 字符处理》- grep/sort/uniq/tr/paste
一:基本 字符处理主要是文本的搜索和处理. 搜索也主要使用到了 管道 作为媒介. 二: grep 搜索文本 基本语法 * grep [-incv] ’文本’ 文件 * i 不区分大小写 * c 匹配行 ...
- webstorm背景颜色更改
一.file --> settings 二.editor-->color scheme 然后右边下拉选择 三.apply -- > ok
- 用promise和async/await分别实现红绿灯
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Python Mock的入门(转)
原文:https://segmentfault.com/a/1190000002965620 Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西. ...
- sublime 可能卡的原因
在重新安装编辑器的时候,配置javascript提示,发现这个插件安装之后,sublime变得非常卡,按照我电脑的性能,同时开着的atom敲代码都不卡.于是把这个插件卸载之后,sublime变得非常流 ...
- 如何监控 Java 垃圾回收机制: jps、jstack、jmap、jhat、jstat
一.MinorGC 一个新对象会被放到eden空间,当eden空间满了的时候,MinorGC就会执行,任何存活的对象,都从eden空间复制到to survivor空间,任何在from survivor ...
- 前端 HTML body标签相关内容 常用标签 表单标签 form里面的 input标签介绍
input标签用于接收用户输入.可以利用input 可以做登录页面 input标签是行内块标签 <input> 元素会根据不同的 type 属性,变化为多种形态. name属性:表单点击提 ...
- H3C 网管交换机快速配置指南(转)
H3C交换机,5XXX,3XXX,还有部分2XXX系列都带有网管功能,可以帮助网络维护非常好的控制网络.基本的配置顺序: Console接口连接,开启Telnet登陆功能,Telnet后进行具体设置. ...
- ipfs私链服务
cd /lib/systemd/system vi ipfs.service [Unit]Description=IPFS[Service]ExecStart=/usr/bin/ipfs daemon ...
- mysql timestamp
select from_unixtime(m.createdAt, '%Y-%m-%d %H:%i:%s') from kfrobotaidlog m; select m.customeruid, ...