netframework中等待多个子线程执行完毕并计算执行时间
本文主要描述在.netframework中(实验环境.netframework版本为4.6.1)提供两种方式等待多个子线程执行完毕。
- ManualResetEvent
在多线程中,将ManualResetEvent实例作为方法传入,线程执行完毕后可以设置标志位来标识当前线程已经执行完毕。代码如下:
List<ManualResetEvent> manualResetEvents = new List<ManualResetEvent>();
/// <summary>
/// ManualResetEvent标志多线程是否执行完毕
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ManualResetEvent_Click(object sender, EventArgs e)
{
// SetBtnEnabled(false);
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = ; i < threadCount; i++)
{
ManualResetEvent manualReset = new ManualResetEvent(false);
manualResetEvents.Add(manualReset);
ThreadPool.QueueUserWorkItem(ManualResetEventMethod, manualReset);
}
//等待所有线程执行完毕
WaitHandle.WaitAll(manualResetEvents.ToArray());
//暂停watch,获取多线程执行时间
watch.Stop();
long time = watch.ElapsedMilliseconds;
lab_time.Text = time.ToString(); // SetBtnEnabled(true); //释放句柄
manualResetEvents.Clear();
} private void ManualResetEventMethod(object obj)
{
Thread.Sleep();
ManualResetEvent mre = (ManualResetEvent)obj;
mre.Set();
}
注意:
在WaitHandle.WaitAll方法中,等待的句柄不能超过64,所以每次用完后,需要手动调用Clear方法进行释放。
如果等待的线程超过64个,可以参考博客:https://www.cnblogs.com/xiaofengfeng/archive/2012/12/27/2836183.html,在该博客中,通过对ManualResetEvent的封装,能够使等待的句柄超过64(测试环境下一次起1000个线程,没有问题)
- Monitor
在主线程中通过Monitor.Wait(locker)达到阻塞的目的,子线程执行完毕通过 Monitor.Pulse(locker)通知主线程,直到所有子线程执行完成,主线程再继续执行,代码如下:
object locker = new object();
int threadCount = ;
int finshCount = ;
/// <summary>
/// Monitor线程之间同步标记多线程执行完毕
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Monitor_Click(object sender, EventArgs e)
{
finshCount = ;
SetBtnEnabled(false);
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = ; i < threadCount; i++)
{
Thread trd = new Thread(new ParameterizedThreadStart(MonitorMethod));
trd.Start(i);
}
lock (locker)
{
while (finshCount != threadCount)
{
Monitor.Wait(locker);//等待
}
}
//所有线程执行完毕,获取执行时间
watch.Stop();
long time = watch.ElapsedMilliseconds;
lab_time.Text = time.ToString(); SetBtnEnabled(true);
} private void MonitorMethod(object obj)
{
Thread.Sleep();
lock (locker)
{
finshCount++;
Monitor.Pulse(locker); //完成,通知等待队列,告知已完,执行下一个。
}
}
在一次开启10、1000个线程两种环境下,分别测试以上两种方式,ManualResetEvent在多次执行时,前几次耗时会比较大,后续耗时会减少并且稳定下来,接近 Monitor的速度。相对而言,Monitor的效率更高。
如果了解过go语言,会发现通过sync包下的WaitGroup也可以达到同样的目的,代码如下:
package main import (
"fmt"
"sync"
"time"
) var wg sync.WaitGroup
var count = 1000 func main() { startTime := time.Now().Unix()
wg.Add(count)
for i := 0; i < count; i++ {
go func() {
defer wg.Done()
time.Sleep(time.Second)
}()
}
fmt.Println("waiting for all goroutine")
wg.Wait() endTime := time.Now().Unix() fmt.Printf("all goroutine is done! time:%v s", (endTime-startTime)) }
相较而言,go语言的协程效率最高
netframework中等待多个子线程执行完毕并计算执行时间的更多相关文章
- Java多线程--让主线程等待所有子线程执行完毕
数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis() ...
- java主线程等待所有子线程执行完毕在执行(常见面试题)
java主线程等待所有子线程执行完毕在执行(常见面试题) java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个 ...
- c#等待所有子线程执行完毕方法
当我们在使用线程中,你会发现主线结束后子线程的结果才显示出来.现在我要等待所以子线程结束,然后在显示结果,怎么做呢? 方法如下: 1.使用 ManualResetEvent,代码如下: using ...
- Java主线程等待所有子线程执行完毕再执行解决办法(转)
方法一: Thread.join()方法,亲测可行,thread.join()方法 Vector<Thread> ts = new Vector<Thread>(); for ...
- CountDownLatch用法---等待多个线程执行完才执行
CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 Coun ...
- C# 多线程join的用法,等待多个子线程结束后再执行主线程
等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...
- java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)
多线程应用中,经常会遇到这种场景:后面的处理,依赖前面的N个线程的处理结果,必须等前面的线程执行完毕后,后面的代码才允许执行. 在我不知道CyclicBarrier之前,最容易想到的就是放置一个公用的 ...
- Java主线程在子线程执行完毕后再执行
一.join() Thread中的join()方法就是同步,它使得线程之间由并行执行变为串行执行. public class MyJoinTest { public static void main( ...
- Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执行
Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执行 Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执 ...
随机推荐
- vue之列表循环
文档:https://cn.vuejs.org/v2/guide/list.html 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略.如果数据项的顺序被改变, ...
- 【linux】【rpm】确定程序是否 rpm 安装
执行 rpm -qf 文件名如果结果显示出安装包那就说明是rpm (或者yum)安装 详情参看 rpm -v (或者 man rpm)
- Python基础(五)——闭包与lambda的结合
(1)变量的域 要了解闭包需要先了解变量的域,也就是变量在哪一段“上下文”是有效的(类似局部变量和全局变量的区别),举一个很简单的例子.(例子不重要,就是涉及闭包就要时刻关注这个域) def test ...
- hdu 3836 tarjain 求强连通分量个数
// 给你一个有向图,问你最少加几条边能使得该图强连通 #include <iostream> #include <cstdio> #include <cstring&g ...
- debian 7 安装vagrant
下载 vagrant_1.4.3_x86_64.deb: $ wget http://966b.http.dal05.cdn.softlayer.net/data-production/2f0b88e ...
- jsp页面上传多个name值到后台
平常利用表单提交的一般都是一个文本框对应一个name,而在后台都是利用request.getParameter(String name);这段代码返回的是一个String类型的参数:而当我们页面上有多 ...
- Python 综合应用小项目一
数据库报错重连机制 利用异常捕获来获取mysql断开的报错,然后再重连 import MySQLdb as mysql class DB: def __init__(self,host,user,pa ...
- 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] C】Greedy Arkady
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举那个人收到了几次糖i. 最好的情况显然是其他人都只收到i-1次糖. 然后这个人刚好多收了一次糖 也即 (i-1)kx + x & ...
- 链表中倒数第k个结点 【微软面试100题 第十三题】
题目要求: 输入一个链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针. 参考资料:剑指offer第15题 题目分析: 1.两个指针,第一个先走k步,然后两个指针同时走,直到第一个走 ...
- Eclipse下创建Spring MVC web程序--maven版
1. 创建一个maven工程: File->New->Other... 2. 创建完成后的结构如下: 3. 配置pom.xml文件,添加spring-webmvc依赖项 <pro ...