本文主要描述在.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中等待多个子线程执行完毕并计算执行时间的更多相关文章

  1. Java多线程--让主线程等待所有子线程执行完毕

    数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis() ...

  2. java主线程等待所有子线程执行完毕在执行(常见面试题)

    java主线程等待所有子线程执行完毕在执行(常见面试题) java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个 ...

  3. c#等待所有子线程执行完毕方法

    当我们在使用线程中,你会发现主线结束后子线程的结果才显示出来.现在我要等待所以子线程结束,然后在显示结果,怎么做呢? 方法如下: 1.使用 ManualResetEvent,代码如下:  using  ...

  4. Java主线程等待所有子线程执行完毕再执行解决办法(转)

    方法一: Thread.join()方法,亲测可行,thread.join()方法 Vector<Thread> ts = new Vector<Thread>(); for  ...

  5. CountDownLatch用法---等待多个线程执行完才执行

    CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 Coun ...

  6. C# 多线程join的用法,等待多个子线程结束后再执行主线程

    等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...

  7. java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)

    多线程应用中,经常会遇到这种场景:后面的处理,依赖前面的N个线程的处理结果,必须等前面的线程执行完毕后,后面的代码才允许执行. 在我不知道CyclicBarrier之前,最容易想到的就是放置一个公用的 ...

  8. Java主线程在子线程执行完毕后再执行

    一.join() Thread中的join()方法就是同步,它使得线程之间由并行执行变为串行执行. public class MyJoinTest { public static void main( ...

  9. Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执行

    Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执行 Semaphore控制同时访问的线程个数countdownlatch等待多个线程执行完本身线程再执 ...

随机推荐

  1. 【linux】 服务器文件说明

    文件名 说明 /etc/resolv.conf  域名解析服务器地址文件 /etc/services 服务程序对应端口号文件 /etc/passwd 登录账号文件 /etc/hosts 本地IP域名解 ...

  2. jQuery将物体居中,并且转换显示和隐藏

    今天来给大家贴一段代码,代码的作用就是利用jQuery将物体居中,并且转换显示和隐藏: 首先建立一个div标签并且写好css样式,具体如下 然后我想要的效果是当我点击了button这个按钮,test可 ...

  3. Spring Cloud构建微服务架构(三)消息总线

     注:此文不适合0基础学习者直接阅读,请先完整的将作者关于微服务的博文全部阅读一遍,如果还有疑问,可以再来阅读此文,地址:http://blog.csdn.net/sosfnima/article/d ...

  4. F查询与Q查询

    F查询 如果我们要对两个字段的值做比较,那该怎么做呢? Django 提供 F() 来做这样的比较.F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值. # 查询评论 ...

  5. python之序列化

    什么叫序列化? 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes. 把字符转换成内存数据类型,叫反序列化. 为什么要序列化? 你 ...

  6. percpu之静态变量

    参考:Linux内核同步机制之(二):Per-CPU变量 CPU私有变量(per-CPU变量) 动态PCPU变量 setup_per_cpu_areas()初始化per-cpu数据. static v ...

  7. UVa - 12096 集合栈计算机(STL)

    [题意] 有一个专门为了集合运算而设计的“集合栈”计算机.该机器有一个初始为空的栈,并且支持以下操作:PUSH:空集“{}”入栈DUP:把当前栈顶元素复制一份后再入栈UNION:出栈两个集合,然后把两 ...

  8. 关于sizeof,对空指针sizeof(*p)可以吗?

    C/C++的sizeof在动态分配内存时经常用到,但之前一直没怎么关注它的具体机制.今天在为一个复杂声明的指针分配内存时,想起来要了解一下sizeof到底是什么? 先抛个问题: 程序运行过程中对空指针 ...

  9. github FATAL:unable to access 'https://github.com/...: Failed to connect to github.com:443; No error

    今天整理github,初次使用,很多都不懂,所以遇到了克隆失败的问题,研究了大半天,后来..... 打开Git Bash,克隆已有工程到本地: $ git clone https://github.c ...

  10. poj2195 bfs+最小权匹配

    题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费1美金,求所有人都进入房子的最小花费,这是典型的二分图带权匹配问题. 这题就是建图有点麻 ...