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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    《Django By Example》第十二章(终章) 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十一章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第十章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第九章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
    《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
    我的superui开源后台bootstrap开发框架
    LayoutInflater 总结
    Android屏幕分辨率概念(dp、dip、dpi、sp、px)
    android studio安装问题
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1611268.html
Copyright © 2011-2022 走看看