多线程协同

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.IO;

namespace WaitOneTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            Console.ReadLine();
        }

        private HashSet<string> m_sAllWork; // 所有工作
        private Queue<string> m_qWaiting; // 等待队列
        private AutoResetEvent m_WorkingEvent = null; // 工作事件
        private AutoResetEvent m_ResumeEvent = null; // 继续事件
        private Thread m_MonitorThread = null; // 监控线程
        private Thread m_WorkingThread = null; // 工作线程
        private Thread m_PatrolThread = null; // 巡逻线程

        public Program()
        {
            Console.WriteLine("Program starting.");

            m_sAllWork = new HashSet<string>();
            m_qWaiting = new Queue<string>();
            m_WorkingEvent = new AutoResetEvent(false);
            m_ResumeEvent = new AutoResetEvent(false);
            m_MonitorThread = new Thread(new ThreadStart(DoMonitor));
            m_WorkingThread = new Thread(new ThreadStart(DoWork));
            m_PatrolThread = new Thread(new ThreadStart(DoPatrol));
            m_MonitorThread.Start();
            m_WorkingThread.Start();
            m_PatrolThread.Start();
            m_WorkingThread.Join();

            Console.WriteLine("Program ending.");
        }

        private void DoWork()
        {
            Console.WriteLine("Work starting.");
            try
            {
                do
                {
                    m_WorkingEvent.Set();
                    string filename = null;
                    try
                    {
                        lock (m_qWaiting)
                        {
                            filename = m_qWaiting.Dequeue();
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        Console.WriteLine("Queue is empty now.");
                        m_ResumeEvent.WaitOne(2000); // 空闲时间(该值要小于巡逻周期值)
                        continue;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Thread - caught Exception - " + e.Message);
                    }
                    Console.WriteLine("Do work. - " + filename);
                    try
                    {
                        Thread.Sleep(new Random().Next(1000, 5000));
                    }
                    catch (ThreadAbortException)
                    {
                        Console.WriteLine("Thread - caught ThreadAbortException - resetting.");
                        lock (m_qWaiting)
                        {
                            m_qWaiting.Enqueue(filename); // 失败的文件加回队列末尾
                        }
                        Thread.ResetAbort(); // 取消中断
                        Thread.Sleep(100); // 睡眠100毫秒,允许外部通过调用Interrupt退出线程。
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Thread - caught Exception - " + e.Message);
                        lock (m_qWaiting)
                        {
                            m_qWaiting.Enqueue(filename); // 失败的文件加回队列末尾
                        }
                    }
                } while (true);
            }
            catch (Exception e)
            {
                Console.WriteLine("Thread - caught Exception - " + e.Message);
            }
            Console.WriteLine("Work ending.");
        }

        private void DoPatrol()
        {
            Console.WriteLine("Patrol starting.");

            try
            {
                do
                {
                    Console.WriteLine("Wait for work method to signal.");
                    // Wait for work method to signal.
                    if (m_WorkingEvent.WaitOne(4000)) // 巡逻周期
                    {
                        Console.WriteLine("Work method signaled.");
                    }
                    else
                    {
                        Console.WriteLine("Timed out waiting for work method to signal.");
                        m_WorkingThread.Abort(); // 中断工作任务(工作线程被卡住,需要中断来恢复,工作线程中通过抓捕相应异常类型进行处理)
                    }
                } while (true);
            }
            catch (Exception e)
            {
                Console.WriteLine("Thread - caught Exception - " + e.Message);
            }

            Console.WriteLine("Patrol ending.");
        }

        private void DoMonitor()
        {
            Console.WriteLine("Monitor starting.");

            try
            {
                lock (m_qWaiting)
                {
                    for (int i = 0; i < 10; i++)
                    {
                        if (!m_sAllWork.Contains(i.ToString()))
                        {
                            m_sAllWork.Add(i.ToString());
                            m_qWaiting.Enqueue(i.ToString());
                        }
                    }
                    if (m_qWaiting.Count > 0)
                        m_ResumeEvent.Set();  // 恢复工作线程(因为工作线程可能处于空闲等待)
                }
                do
                {
                    // 随机时间内产生一个工作任务
                    Thread.Sleep(new Random().Next(1000, 60000));
                    int i = new Random().Next(1, 1000);
                    if (!m_sAllWork.Contains(i.ToString()))
                    {
                        m_sAllWork.Add(i.ToString());
                        m_qWaiting.Enqueue(i.ToString());
                        m_ResumeEvent.Set(); // 恢复工作线程(因为工作线程可能处于空闲等待)
                    }
                } while (true);
            }
            catch (Exception e)
            {
                Console.WriteLine("Thread - caught Exception - " + e.Message);
            }

            Console.WriteLine("Monitor ending.");
        }
    }
}
时间: 2024-10-10 21:50:32

多线程协同的相关文章

黑马程序员——Java基础知识之多线程协同

多线程协同 线程间的通讯:对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤,但是他们共享了一个资源. 怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,用对象把这车装满,现在一车装一个对象. 等待唤醒机制: 用的不是sleep是wait.flag标记,这是两人沟通的方式.其实每个标记就要做一次等待或者notify,判断wait,改值notify.线程池.notify唤醒里面的线程,按顺序唤醒.wait和notify必须用在

C#多线程实践——线程状态

线程状态关系图 在.NET Framework中,可以通过ThreadState属性获取线程的执行状态.上图标识出三种状态“层”,ThreadState以按位计算的方式组合状态层,每种状态层的成员之间都是互斥的,下面是所有的三种状态“层”: 运行 (running) / 阻止 (blocking) / 终止 (aborting) 状态(上图显示) 后台 (background) / 前台 (foreground) 状态 (ThreadState.Background) 不建议使用的Suspend

黑马程序员——Java多线程基础知识2

多线程协同 线程间的通讯:我们对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤.但是他们共享了一个资源. 怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,我用对象把这车装满,现在一车装一个对象. 等待唤醒机制: 用的不是sleep是wait.flag标记,这是两人沟通的方式.其实每个标记就要做一次等待或者notify,判断wait,改值notify.线程池.notify唤醒里面的线程,按顺序唤醒.wait和notify必

Java后台工程师面试杂记——不跳不涨工资星人跳槽经历

经过接近一个月的时间,完成换工作这件“小事”,前后总计面试了多家公司,最后也没接到几个offer,不过最终总算尘埃落定,就对这个过程进行一个总结吧. 在某互联网公司工作了近一年的时间,但是频繁的业务需求和大强度的加班,无聊的工作内容以及公司就要搬家的前景,促成了自己换工作的打算,在做出这个打算之后几乎立即就和老大说了这件事情,这个举动结果有好有坏,正面意义是我请假或是懒得请假去参加面试的时候,显得没啥心理负担,负面影响就是如果短时间找不到就只能先滚犊子了.因为面试的是Java后台开发,而且是属于

理解和使用SQL Server中的并行

什么是并行? 我们从小就听说过"人多力量大"."人多好办事"等,其思想核心就是把一个任务分给许多人,这样每个人只需要做很少的事情就能完成整个任务.更重要的是,如果额外的人专门负责分配工作,那么任务的完成时间就可以大幅减少了. 数糖豆 设想你正面对一个装满各式各样糖豆的罐子,并且要求书有多少个.假设你能平均每秒数出五个,需要大于十分钟才能数完这个盒子里的3027个糖豆. 如果你有四个朋友帮助你去做这个任务.你就有了多种策略来安排这个数糖豆任务,那让我们模仿SQLSer

转载一篇将C/C++ 与lua混合使用讲的比较入门的文章

转自 http://www.open-open.com/home/space-6246-do-blog-id-1426.html Lua是一个嵌入式的脚本语言,它不仅可以单独使用还能与其它语言混合调用.Lua与其它脚本语言相比,其突出优势在于: 可扩展性.Lua的扩展性非常卓越,以至于很多人把Lua用作搭建领域语言的工具(注:比如游戏脚本).Lua被设计为易于扩展的,可以通过Lua代码或者 C代码扩展,Lua的很多功能都是通过外部库来扩展的.Lua很容易与C/C++.java.fortran.S

Redis的字典扩容与ConcurrentHashMap的扩容策略比较

本文介绍Redis的字典(是种Map)扩容与ConcurrentHashMap的扩容策略,并比较它们的优缺点. (不讨论它们的实现细节) 首先Redis的字典采用的是一种''单线程渐进式rehash'',这里的单线程是指只有一个线程在扩容, 而在扩容的同时其他的线程可以并发的进行读写. Redis系统后台会定时给予扩容的那个线程足够的运行时间,这样不会导致它饿死. 大致过程是这样的: ht[0],是存放数据的table,作为非扩容时容器. ht[1],只有正在进行扩容时才会使用,它也是存放数据的

死磕 java集合之ConcurrentHashMap源码分析(三)

本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样,都是先找到元素所在的桶,然后采用分段锁的思想锁住整个桶,再进行操作. public V remove(Object key) { // 调用替换节点方法 return replaceNode(key, null, null); } final V replaceNode(Object key, V

BUAA_OO 第二单元总结

BUAA_OO 第二单元总结 写在前面 ? 多线程(multi-threading)是指从软件或硬件上实现多个线程并发执行的技术.现代处理器普遍具有多核的特点,支持同一时间执行多个线程,使用多线程技术可以提高程序并发度,整体提高处理性能.因此掌握多线程程序设计技术是CS学习必不可少的一部分. ? 多线程程序设计包括线程协同控制.线程安全保证以及线程程序设计模式等.本文主要总结OO课程第二单元所学的有关多线程程序设计的知识,实践体会,以及技术注记,以备后用. 第五次作业 ? 第五次作业实现了一个单