zoukankan      html  css  js  c++  java
  • AutoResetEvent详解

    在MSDN中,它的解释为:通知正在等待的线程已发生事件。无法继承此类(密封类)。

    AutoResetEvent 允许线程通过发信号进行相互通信,例如发Set信号,让正在WaitOne等待信号着的线程开启继续执行。通常,此通信涉及线程需要独立访问的资源。

    线程通过调用 AutoResetEvent 上的WaitOne来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程通过调用 Set发出资源可用的信号。

    调用 Set 向 AutoResetEvent 发信号以释放等待线程,这里释放的是有WaitOne等待着的随机的某一个线程 ,而不是所有有WaitOne等待信号的线程,此时AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。如果没有任何线程在等待(没有一个线程有WaitOne等待信号),则状态将无限期地保持为终止状态。

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

    示例代码:

    实现类源码:

    class AutoResetEventTest
        {
            private AutoResetEvent are;
    
            public AutoResetEventTest()
            {
                this.are = new AutoResetEvent(false);
            }
    
            /// <summary>
            /// 放行等待的线程
            /// </summary>
            public void Set()
            {
                this.are.Set();
            }
    
            /// <summary>
            /// 暂停正在等待的线程
            /// </summary>
            public void Reset()
            {
                this.are.Reset();
            }
    
            /// <summary>
            /// 启动N个线程,可以手动传入参数指定启动几个线程
            /// </summary>
            /// <param name="threadNumber"></param>
            public void CreateThreads(int threadNumber)
            {
                Thread[] threads = new Thread[threadNumber];
    
                for (int i = 0; i < threadNumber; i++)
                {
                    threads[i] = new Thread(new ThreadStart(Run));
                    threads[i].Start();
                }
            }
    
            /// <summary>
            /// 正在等待着的线程,该线程打印出线程ID
            /// </summary>
            private void Run()
            {
                string threadId = string.Empty;
                try
                {
                    while (true)
                    {
                        // 阻塞当前线程
                        this.are.WaitOne();
    
                        threadId = Thread.CurrentThread.ManagedThreadId.ToString();
                        Console.WriteLine("Run---Thread(" + threadId + ") is running...");
    
                        Thread.Sleep(3000);
                    }
                }
                catch (Exception ex)//异常处理
                {
                    Console.WriteLine("Run---Thread(" + threadId + ") Error happend!:" + ex.Message.ToString());
                }
            }
    
        }

    主函数源码:

    在控制台界面上输入run会看到某个等待着的线程被开启:

        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("**********************************");
                Console.WriteLine("请输入"run"开启正在等待着的线程...");
                Console.WriteLine("********************************
    ");
    
                AutoResetEventTest test = new AutoResetEventTest();
    
                test.CreateThreads(10);
    
                while (true)
                {
                    string input = Console.ReadLine();
                    if (input.Trim().ToLower() == "run")
                    {
                        Console.WriteLine("WaitOne等待着的某个线程开启运行...");
                        test.Set();
                    }
                }
    
            }
        }

    运行结果:

    当输入一次run时,显示如下:

    由于初始化AutoResetEvent 事件为false,则该事件处于非终止状态,故所有等待着的线程在没有Set信号到来时,都将暂停运行,当输入一次run,调用AutoResetEvent 的Set方法,将会随机开启某一个正在等待着的线程,当该等待着的线程被释放,则AutoResetEvent 自动的变为非终止状态,其余的等待线程想要开启就必须等待再一次Set信号。

    当输入多次run时,显示结果如下:

    每输入一次run都会调用AutoResetEvent 事件的Set方法,将会随机开启某一个正在等待着的线程,当这个线程被释放后,则AutoResetEvent  事件会自动的置为非终止状态,那么刚刚被开启的线程将会再次等待,直到等待下一次Set信号将它开启。

    假如我们初始化将AutoResetEvent 事件设置为true,则在控制台下会看到如下结果:

    这是因为初始化将AutoResetEvent 事件设置为true,则它会处于终止状态,那么会初次开启某个线程,当这个等待着的线程被释放时,则会自动将AutoResetEvent 设置成非终止状态,直到有Set信号给某个等待着的线程,才会开启这个等待着的线程。

    如下:

    再一次输入run,

    调用AutoResetEvent  的Set方法,将会随机的开启某一个正在等待着的线程,线程释放完毕后会自动将AutoResetEvent 置为非终止状态,所以每当run一次只能看到一次随机等待的线程在跑

     
  • 相关阅读:
    mysql数据库——特殊sql语句整理之修改表结构
    mysql数据库引擎——MyISAM,InnoDB
    Golang程序性能分析
    Docker基本操作
    go module
    Docker基础原理
    基于zookeeper或redis实现分布式锁
    漫谈微服务
    快速排序
    设计模式泛谈
  • 原文地址:https://www.cnblogs.com/vpersie2008/p/4077896.html
Copyright © 2011-2022 走看看