zoukankan      html  css  js  c++  java
  • c# 多线程系列二 自定义线程执行器

    看了第一篇文章,多线程系列,看到了在线程执行任务队列有了一定的了解~!

    那么今天我来讲讲,怎么样构建通用的自定义线程概念!

    线程执行任务,肯定要有目标,但是如果写死了,那么一个线程处理执行职能按照思路处理一类任务,显然不满足我们的实际场景的需求,那么怎么才能创建灵活的线程执行器呢!

    首先我们来创建一个任务构造器!

     1   /// <summary>
     2     /// 线程模型执行任务 基类
     3     /// </summary>
     4     public abstract class BaseTask
     5     {
     6 
     7         /// <summary>
     8         /// 任务ID
     9         /// </summary>
    10         public long TID { get; set; }
    11 
    12         /// <summary>
    13         /// 任务名称
    14         /// </summary>
    15         public string TName { get; set; }
    16 
    17         /// <summary>
    18         /// 线程模型任务
    19         /// </summary>
    20         public abstract void Run();
    21 
    22         public override string ToString()
    23         {
    24             return "Task<" + this.TName + "(" + TID + ")>";
    25         }
    26     }

    看到这里,可能不会明白,这么写法的意义在哪里呢?

    那么我们再来自定义线程的执行器

     1 /// <summary>
     2     /// 定义自定义线程模型
     3     /// </summary>
     4     public abstract class BaseThread<T> where T : BaseTask
     5     {
     6         //执行线程
     7         Thread _Thread;
     8         //通知一个或多个正在等待的线程已发生事件
     9         ManualResetEvent mre = new ManualResetEvent(false);
    10         //线程安全的队列
    11         System.Collections.Concurrent.ConcurrentQueue<T> cqueue = new System.Collections.Concurrent.ConcurrentQueue<T>();
    12 
    13         /// <summary>
    14         /// 自定义线程ID;
    15         /// </summary>
    16         public long TID { get; set; }
    17 
    18         public static bool IsRuning = true;
    19 
    20         /// <summary>
    21         /// 初始化
    22         /// </summary>
    23         /// <param name="tName">线程的名称</param>
    24         public BaseThread(string tName)
    25         {
    26             _Thread = new Thread(Runing);
    27             _Thread.Name = tName;
    28             _Thread.Start();
    29         }
    30 
    31         //模拟新增任务
    32         public void AddTask(T task)
    33         {
    34             //添加任务到队列
    35             cqueue.Enqueue(task);
    36             //唤醒所有相关的挂起线程
    37             mre.Set();
    38         }
    39 
    40         void Runing()
    41         {
    42             //主循环 服务器运行标识
    43             while (IsRuning)
    44             {
    45                 //如果是空则继续等待      服务器运行标识
    46                 while (cqueue.IsEmpty && IsRuning)
    47                 {
    48                     //重置线程暂停状态
    49                     mre.Reset();
    50                     //这个操作是以便服务器需要停止操作,
    51                     //如果停止调用线程的Thread.Abort()是会导致处理队列任务丢失
    52                     mre.WaitOne(2000);
    53 #if DEBUG
    54                     //为了方便测试信息打印的暂停信息
    55                     Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Status Sleep");
    56 #endif
    57                 }
    58                 T t;
    59                 //取出队列任务
    60                 if (cqueue.TryDequeue(out t))
    61                 {
    62                     Runing(t);
    63                 }
    64             }
    65         }
    66 
    67         /// <summary>
    68         /// 设置运行方法为虚方法,方便子函数覆盖
    69         /// </summary>
    70         protected virtual void Runing(T run)
    71         {
    72             try
    73             {
    74                 //执行任务
    75                 run.Run();
    76                 //打印任务信息
    77                 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Action:" + run.ToString());
    78             }
    79             catch (Exception ex)
    80             {
    81                 //打印任务信息
    82                 Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + " Action:" + run.ToString() + " Exception:" + ex);
    83             }
    84         }
    85     }

    看到这里是不是比较清楚了?这样我们定义的线程是不是能完成多不同类型的任务呢?

    是不是可以做到一个线程执行和处理不同类型的任务呢?

    接下来我们创建类型的实现类

    任务实现类1

     1 /// <summary>
     2     /// 测试任务
     3     /// </summary>
     4     public class TestTask : BaseTask
     5     {
     6 
     7         public override void Run()
     8         {
     9             Console.WriteLine("我只是用来测试的");
    10         }
    11     }

    任务实现类2

     1 public class TestTask1 : BaseTask
     2     {
     3 
     4         /// <summary>
     5         /// 执行任务
     6         /// </summary>
     7         public Action Test { get; set; }
     8 
     9         public override void Run()
    10         {
    11             if (Test != null)
    12             {
    13                 Test();
    14             }
    15             Console.WriteLine("我只是用来测试的");
    16         }
    17     }


    线程的实现类

     1     /// <summary>
     2     /// 测试线程
     3     /// </summary>
     4     public class TestThread : BaseThread<BaseTask>
     5     {
     6         public TestThread()
     7             : base("TestThread")
     8         {
     9 
    10         }
    11     }


    接下来我们看看测试效果

     1     class Program
     2     {
     3 
     4         static void Main(string[] args)
     5         {
     6             TestThread tt = new TestThread();
     7             tt.AddTask(new TestTask() { TID = 1, TName = "测试1" });
     8             tt.AddTask(new TestTask1() { TID = 2, TName = "测试2" });
     9             tt.AddTask(new TestTask1() { TID = 2, TName = "测试3", Test = new Action(() => { Console.WriteLine("我要暂停3秒钟"); Thread.Sleep(3000); }) });
    10             tt.AddTask(new TestTask() { TID = 3, TName = "测试4" });
    11             Console.ReadLine();
    12         }
    13     }

    运行结果图

    看到这里是不是很清楚明了呢?这样我们在处理日常任务的时候,不同类型的逻辑或者任务类型,是不是都可以放到一个线程执行呢?

    请大家期待我的下一篇文章,为大家讲解,定时器线程执行器,

    跪求保留标示符
    /**
     * @author: Troy.Chen(失足程序员, 15388152619)
     * @version: 2021-07-20 10:55
     **/
    
    C#版本代码 vs2010及以上工具可以
    
    java 开发工具是netbeans 和 idea 版本,只有项目导入如果出现异常,请根据自己的工具调整
    
    
    提供免费仓储。
    最新的代码地址:↓↓↓
    https://gitee.com/wuxindao
    
    觉得我还可以,打赏一下吧,你的肯定是我努力的最大动力
        
    
  • 相关阅读:
    为什么需要Docker?
    一分钟学会《模板方法模式》
    2018再见|2019你好
    三分钟学会《门面模式》
    策略模式原来这么简单!
    外行人都能看得懂的机器学习,错过了血亏!
    我是如何将博客转成PDF的
    面试前必须知道的MySQL命令【explain】
    count(*)、count(1)和count(列名)的区别
    Linux shell去除字符串中所有空格
  • 原文地址:https://www.cnblogs.com/shizuchengxuyuan/p/4335452.html
Copyright © 2011-2022 走看看