zoukankan      html  css  js  c++  java
  • 多线程中的ManualResetEvent

    先来看一下简单的多线程控制台程序:

    using System;
    using System.Threading;

    namespace ManualResetEventStudy
    {

        
    class ThreadClass
        {
            
    static void t1()
            {
                
    for (int x = 1; x <= 5; x++)
                {
                    Thread.Sleep(
    500);
                    Console.WriteLine(
    "t1的x:" + x);
                }
            }

            
    static void t2()
            {
                
    for (int x = 1; x <= 5; x++)
                {
                    Thread.Sleep(
    500);
                    Console.WriteLine(
    "t2的x:" + x);
                }
            }

            
    static void Main(string[] args)
            {
                Thread thrd1 
    = new Thread(t1);
                thrd1.Start();

                Thread thrd2 
    = new Thread(t2);
                thrd2.Start();


                
    for (int x = 1; x <= 5; x++)
                {
                    Thread.Sleep(
    500);
                    Console.WriteLine(
    "主线程中的x:" + x);
                }

                Console.Read();
            }       
        }
    }

     入口方法Main里,创建了二个线程,分别调用方法t1与t2,再加上主线程本身,一并有三个线程,运行后,三个线程都在计数输出,结果类似如下:

    t2的x:1
    t1的x:1
    主线程中的x:1
    t2的x:2
    t1的x:2
    主线程中的x:2
    t2的x:3
    t1的x:3
    主线程中的x:3
    t2的x:4
    t1的x:4
    主线程中的x:4
    t2的x:5
    t1的x:5
    主线程中的x:5

    三个线程的顺序,在这段代码中我们是无法控制的,天知道谁先开始/谁先结束,反正都是"并行"处理,完全看CPU当时的心情  :)

    问题:如果需求有变化,比如要求在主线程执行到某个特定的位置(或时间点)时,才让其它线程开始介入,该怎么做呢?(这种情况实际中很常见,比如某一项计算的入口参数依赖于另一项计算的结果,再比如我们计算月工资前,得先统计出员工当月考勤情况)

    System.Threading命名空间下有一个ManualResetEvent类,可以做到这一点:

    using System;
    using System.Threading;

    namespace ManualResetEventStudy
    {

        
    class ThreadClass
        {       

            
    static ManualResetEvent mre = new ManualResetEvent(false);

            
    static void t1()
            {
                
    mre.WaitOne(1000);//等待1秒后,自行启动
                for (int x = 1; x <= 5; x++)
                {
                    Thread.Sleep(
    500);
                    Console.WriteLine(
    "t1的x:" + x);
                }
            }

            
    static void t2()
            {
                
    mre.WaitOne();//一直等待下去,直到有"人"调用mre.set()发出信号为止
                for (int x = 1; x <= 5; x++)
                {
                    Thread.Sleep(
    500);
                    Console.WriteLine(
    "t2的x:" + x);
                }
            }

            
    static void Main(string[] args)
            {
                Thread thrd1 
    = new Thread(t1);
                thrd1.Start();

                Thread thrd2 
    = new Thread(t2);
                thrd2.Start();


                
    for (int x = 1; x <= 5; x++)
                {
                    Thread.Sleep(
    500);
                    Console.WriteLine(
    "主线程中的x:" + x);

                    if (x == 3
                    {
                        mre.Set();//通知所有等待的线程:“同志们,可以动啦”:)
                    }
                }

                Console.Read();
            }        

        }
    }

     t1方法中,我们用 mre.WaitOne(1000);让调用该方法的线程先等候1秒,t2方法中,我们用mre.WaitOne()无限等候,然后主线程中计数到3的时候,手动调用mre.Set()方法唤醒所有等候中的线程,运行结果类似下面这样:

    主线程中的x:1
    主线程中的x:2
    t1的x:1
    主线程中的x:3
    t1的x:2
    t2的x:1
    主线程中的x:4
    t1的x:3
    主线程中的x:5
    t2的x:2
    t1的x:4
    t2的x:3
    t1的x:5
    t2的x:4
    t2的x:5

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    WebAPI跨域问题处理
    WebAPI学习及Swagger使用
    MSMQ消息队列总结
    学习笔记——泛型
    学习笔记——并行编程Parallel
    学习笔记——多线程
    学习笔记——线程 Thread
    springboot,maven依赖引用失败,手动将jar包导入maven本地仓库
    PostgreSQL如何实现MySQL中的group_concat聚集函数(简单的拼接功能)
    mybatis的XML配置文件sql查询中,传入对象参中某个字段为list时,sql编写方式。
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1611268.html
Copyright © 2011-2022 走看看