zoukankan      html  css  js  c++  java
  • 线程同步等待所有线程执行完毕

    在多线程程序中经常会碰到线程同步:

    场景1

    主线程启动多个子线程后,主线程需要等待所有的子线程执行完毕后,主线程才能进一步向下执行。

    C# 提供了 ManualResetEvent 类为我们的线程同步提供了方便.

    ManualResetEvent.WaitAll(new WaitHandle[] { });

    WaitAll静态方法提供了阻塞当前线程的执行,直到WaitHandle[]中的每个线程发送了阻塞解除的信号,当前线程才会继续执行。

    可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。

    ManualResetEvent.Set() 方法发送阻塞终止的信号,当其它线程收到线程阻塞解除的信号,就会继续执行。

    场景:主线程需要对子线程1产生的数据与子线程2产生的数据求和,主线程启动线程1等待生成数据1,启动线程2等待生成数据2,只有当

    数据1与数据2生成后,主线程才能对数据求和。

    代码如下:

    using System;
    
    using System.Collections.Generic;
    
    using System.Linq;
    
    using System.Text;
    
    using System.Threading;
    
    using System.Diagnostics;
    
    namespace ThreadStudy.Hbb0b0
    
    {
    
        /// <summary>
    
        /// 本事例说明主线程如何等待辅助线程都执行完毕之后继续执行。
    
        /// 主线程启动辅助线程1生成加数1,启动辅助线程2生成加数2
    
        /// 主线程等待辅助线程1与辅助线程2的生成的加数之后,对加数
    
        /// 进行累加,并输出结果。
    
        /// </summary>
    
        class Program
    
        {
    
            delegate int operateNumber(int a, int b);
    
            delegate int generateNumber(int a);
    
            static int result1;
    
            static int result2;
    
            static void Main(string[] args)
    
            {
    
                //辅助线程1阻塞标志
    
                ManualResetEvent m1 = new ManualResetEvent(false);
    
               
    
                //辅助线程2的阻塞标志
    
                ManualResetEvent m2 = new ManualResetEvent(false);
    
     
    
                generateNumber g1 = ThreadTool.GenerateNumber;
    
                generateNumber g2 = ThreadTool.GenerateNumber;
    
                AsyncCallback g1_callback = delegate(IAsyncResult ar)
    
                {
    
                    result1 = g1.EndInvoke(ar);
    
                    Console.WriteLine("thread id:{0} current number:{1} block stop", Thread.CurrentThread.ManagedThreadId, result1);
    
                    //辅助线程阻塞完毕
    
                    m1.Set();
    
                };
    
                AsyncCallback g2_callback = delegate(IAsyncResult ar)
    
                {
    
                    result2 = g2.EndInvoke(ar);
    
                    Console.WriteLine("thread id:{0} current number:{1} block stop", Thread.CurrentThread.ManagedThreadId, result2);
    
                    //辅助线程阻塞完毕
    
                    m2.Set();
    
                };
    
                Console.WriteLine("generate numbers:");
    
     
    
                //辅助线程1启动
    
                g1.BeginInvoke(10, g1_callback, null);
    
               
    
                //辅助线程2启动
    
                g2.BeginInvoke(100, g2_callback, null);
    
     
    
                //主线线程等待所有辅助线程回归
    
                ManualResetEvent.WaitAll(new WaitHandle[] { m1, m2 });
    
     
    
                int sum= ThreadTool.sum(result1, result2);
    
                Console.WriteLine("{0}+{1}={2}", result1, result2, sum);
    
     
    
                Console.Read();
    
     
    
            }
    
        }
    
        public class ThreadTool
    
        {
    
            /// <summary>
    
            /// 生成数字
    
            /// </summary>
    
            /// <param name="maxNum"></param>
    
            /// <returns></returns>
    
            static public int GenerateNumber(int maxNum)
    
            {
    
                Console.WriteLine("thread Id:{0} generate number", Thread.CurrentThread.ManagedThreadId);
    
                Thread.Sleep(5000);
    
            
    
                int result = new Random((int)DateTime.Now.Ticks).Next(maxNum);
    
                return result;
    
            }
    
            /// <summary>
    
            /// 累加结果
    
            /// </summary>
    
            /// <param name="a"></param>
    
            /// <param name="b"></param>
    
            /// <returns></returns>
    
            static public int sum(int a, int b)
    
            {
    
                Console.WriteLine("thread Id:{0} gernerate number", Thread.CurrentThread.ManagedThreadId);
    
                Thread.Sleep(6000);
    
                return a + b;
    
            }
    
        }
    
    }

    场景2 :

    主线程启动子线程1,子线程2, 只要子线程1或子线程2 任一线程执行完毕,主线程就可以继续执行。

    代码如下:

    using System;
    
    using System.Collections.Generic;
    
    using System.Linq;
    
    using System.Text;
    
    using System.Threading;
    
    namespace ThreadWaitOne
    
    {
    
     
    
        class ThreadStartParameterInfo
    
        {
    
            /// <summary>
    
            /// 线程信号
    
            /// </summary>
    
            public ManualResetEvent m_mr;
    
           
    
            /// <summary>
    
            /// 线程等待时间
    
            /// </summary>
    
            public int m_waitTicks;
    
            public ThreadStartParameterInfo(ManualResetEvent mr,int waitTicks)
    
            {
    
                m_mr = mr;
    
                m_waitTicks = waitTicks;
    
              
    
            }
    
        }
    
     
    
        public class ThreadTool
    
        {
    
            private object m_SyncObject = new object();
    
            private int currentThreadId = -1;
    
            public void Main()
    
            {
    
                for (int i = 0; i < 5; i++)
    
                {
    
                    ManualResetEvent mr1 = new ManualResetEvent(false);
    
                    ManualResetEvent mr2 = new ManualResetEvent(false);
    
                    ManualResetEvent mr3 = new ManualResetEvent(false);
    
                    ParameterizedThreadStart pts1 = new ParameterizedThreadStart(this.GenerateNumber);
    
                    ParameterizedThreadStart pts2 = new ParameterizedThreadStart(this.GenerateNumber);
    
                    ParameterizedThreadStart pts3 = new ParameterizedThreadStart(this.GenerateNumber);
    
                    Thread ts1 = new Thread(pts1);
    
                    Thread ts2 = new Thread(pts1);
    
                    Thread ts3 = new Thread(pts1);
    
                    ts1.Start (new ThreadStartParameterInfo(mr1, 3010));
    
                    ts2.Start(new ThreadStartParameterInfo(mr2, 3020));
    
                    ts3.Start(new ThreadStartParameterInfo(mr3, 3030));
    
                    //主线程等待任一线程,任一线程发送阻塞完成信号后,主线程就可以继续执行
    
                    ManualResetEvent.WaitAny(new WaitHandle[] { mr1, mr2, mr3 });
    
     
    
                    Console.WriteLine("Main Thread: The fast thread:{0}", currentThreadId);
    
                }
    
               
    
            }
    
     
    
            public void GenerateNumber(object  resetEvent)
    
            {
    
                ThreadStartParameterInfo threadInfo = resetEvent as ThreadStartParameterInfo;
    
                //ManualResetEvent mr = resetEvent as ManualResetEvent;
    
                Console.WriteLine("thread Id:{0} wait:{1} generate number start:.....", Thread.CurrentThread.ManagedThreadId,threadInfo.m_waitTicks);
    
               
    
                Thread.Sleep(threadInfo.m_waitTicks);
    
                int radomNumber = new Random((int)DateTime.Now.Ticks).Next(1000);
    
                lock(m_SyncObject)
    
                {
    
                    currentThreadId = Thread.CurrentThread.ManagedThreadId;
    
                }
    
                Console.WriteLine("thread Id:{0} generate number:{1}", Thread.CurrentThread.ManagedThreadId, radomNumber);
    
                threadInfo.m_mr.Set();
    
            }
    
        }
    
    }

     

  • 相关阅读:
    ADT上跑java application
    GIT 用RSA加密方式来记住密码
    android中listView下有Button按钮始终在最底部
    Android学习:导入工程时报错The import android cannot be resolved
    Preference的使用
    MySQL查询时,查询结果如何按照where in数组排序
    MySQL创建民族表的SQL语句
    PHP 使用GD库合成带二维码和圆形头像的海报步骤以及源码实现
    使用file_get_contents()和curl()抓取网络资源的效率对比
    常用正则表达式整理(持续更新中)
  • 原文地址:https://www.cnblogs.com/hbb0b0/p/2919159.html
Copyright © 2011-2022 走看看