多线程之线程池任务管理通用模板

已经一年多的时间没有使用多线程了.最近需要做一个异步发邮件的功能,为了给同事写一个例子,想起以前写的爬虫的时候,

一个带我的人给了我一个通用的模板类, 我觉得那个例子很好,于是我根据自己的理解,写出了如下的代码.

首先是一个通用的 计数器.包括 当前在运行的线程数Current,执行成功的数量Success,执行失败的数量Error,以及总完成数量Finish.

为了方便大家理解,我还是做一下简要的说明.大致过程是这样的: 首先有一批任务进来,需要把这些任务用多线程来处理.(我这里使用的是线程池.)

关于池的概念大家应该埠陌生.比如 数据库的连接池.

任务一个一个的分配,每个任务都是开启一个子线程单独执行的,一边分配任务,一边执行任务.在不停的分配任务的时候,会出现这样一种情况,

就是任务已经分配出去很多了,但是执行的不够快,这个时候需要主线程等待一下,过一会再分配新的任务.

我将上面的描述用一个日常生活中的例子来做说明: 一个小饭店只有10个座位,10点开始营业,到了12点吃饭的时间,外面来了100个客人,

挨个挨个的进入饭店就餐.

第一个人进,占位置1个,

第二个人进入, 占位置1个,

第三个人进入,占位置1个,

第四个人进入占位置1个,

第五个人进入占位置1个,  然后第一个人打包的走了,有个位置空出来了,

现在已经使用了 4个位置,至于进来以后坐什么地方,这个不用管.

第六个人进入占了位置1个,...第九个人进来了,占位置1个,第2个人吃完了,第十个人进来了,第是一个人进来了,第十二个人进来了,

第三个人吃完了,第十三个人进来了,

第十四个人想进来,抱歉,已经坐满了,要等待,过1分钟再看有没有位置,如果没有人离开,外面的人一直不能进来,

过了五分钟, 再看发现一个桌子四个人都离开了,于是第十四个人进来了,第十五个人进来了....后面的类似前面的...

废话啰嗦完了,上代码

1.先上一个计数器读写的类

 public sealed  class ThreadCounter
    {
         private int current = 0;
         private int error = 0;
         private int success = 0;
         private int finish = 0;

         private static object writeObj = new object();

         public int getCurrent()
         {
             int res = 0;
             lock (writeObj)
             {
                 res = current;
             }
             return res;
         }

         public int getError()
         {

             int res = 0;
             lock (writeObj)
             {
                 res = error;
             }
             return res;
         }

         public  int getSuccess()
         {
             int res = 0;
             lock (writeObj)
             {
                 res = success;
             }
             return res;
         }

         public int getFinish()
         {
             int res = 0;
             lock (writeObj)
             {
                 res = finish;
             }
             return res;
         }

         public void setAddCurrent()
         {
             lock (writeObj)
             {
                 current++;
             }
         }

         public  void setSuccess()
         {

             lock (writeObj)
             {
                 success++;
                 current--;
             }

         }

         public  void setError()
         {
             lock (writeObj)
             {
                 error++;
                 current--;
             }
         }

         public void setFinish()
         {
             lock (writeObj)
             {
                 finish++;
             }
         }

    }

2.主体运行业务处理类

 public class RunManager
    {
        public RunManager() { }

        public int ThreadCount { get; set; }

        private static int MaxThreadCount = 10;

        /// <summary>
        /// 最大开启的线程数
        /// </summary>
        /// <param name="threadCount"></param>
        public void RunStart(int threadMaxCount)
        {
            //最大开启的线程数
            Console.WriteLine("设置最大线程数:" + threadMaxCount);

            MaxThreadCount = threadMaxCount;
            RunTask(100);
        }

        public void RunTask(int taskCount)
        {
            string mss = "";

            string[] arr = new string[] {"|","/","-","\\" };
            int j = 0;
            while (true)
            {
                j++;
                if (j==4)
                {
                    j = 0;
                }
                Console.Clear();
                Console.SetCursorPosition(1, 0);
                Console.WriteLine("当前运行情况");
                Console.Write("["+arr[j]+"]\t");
                 mss = string.Format("Query:{0} , Current:{1} , Success:{2} , Error:{3} , Finish:{4}", taskCount, tc.getCurrent(),tc.getSuccess(), tc.getError(), tc.getFinish());
                Console.WriteLine(mss);
                Thread.Sleep(500);

                if (taskCount>0&&tc.getCurrent() < MaxThreadCount)
                {
                    taskCount--;
                    tc.setAddCurrent();
                    ThreadPool.UnsafeQueueUserWorkItem(RuanCallBack, 0);
                }
                else if (taskCount==0)
                {
                    taskCount = random.Next(60, 125);
                }
                else if (tc.getCurrent() >= MaxThreadCount)
                {
                    Thread.Sleep(6000);
                }

            }

        }

        ThreadCounter tc = new ThreadCounter();
        Random random = new Random();
        public void RuanCallBack(object parms)
        {
            // 将传过来的参数, 整理为要查询的数据, 以及处理数据,写入文件,打包zip,
            // 发送邮件通知用户下载
            try
            {
                int t = random.Next(3, 7);
                Thread.Sleep(t * 1000);

                tc.setSuccess();
            }
            catch (Exception)
            {
                tc.setError();
            }
            finally
            {
                tc.setFinish();
            }

            //Console.WriteLine("当前线程序号:" + parms.ToString() + "\t线程停顿时间:" + t);
        }

    }

3.调用

        static void Main(string[] args)
        {
            RunManager r = new RunManager();
            r.RunStart(20);
            Console.Read();
            Console.WriteLine("运行结束");

        }

先来看看运行效果

Nice!

原代码下载: 下载

时间: 2024-10-30 03:08:35

多线程之线程池任务管理通用模板的相关文章

多线程及线程池学习心得

一.线程的应用与特点 多线程是程序员不可或缺的技术能力,多线程技术在各个方面都有应用,特别在性能优化上更是起到至关重要的作用.但是,如果多线程写得不好,往往会适得其反,特别是高并发时会造成阻塞.超时等现象.多线程具有以下特点:1.独立性,拥有自己独立的资源,拥有自己私有的地址空间:2.动态性,进程具有自己的生命周期和各种不同的状态:3.并发性,多个进程可以在单个处理器上并发执行,不会相互影响,并行是指同一时刻有多条指令在多个处理器上同时执行.线程是进程的组成部分,一个进程可以拥有多个线程,一个线

C#多线程之线程池篇3

在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关知识. 五.使用等待句柄和超时 在这一小节中,我们将学习如何在线程池中实现超时和正确地实现等待.具体操作步骤如下: 1.使用Visual Studio 2015创建一个新的控制台应用程序. 2.双击打开"Program.cs"文件,编写代码如下所示: 1 using System; 2 u

C#多线程之线程池篇2

在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我们将学习对于大量的异步操作,使用线程池和分别使用单独的线程在性能上有什么差异性.具体操作步骤如下: 1.使用Visual Studio 2015创建一个新的控制台应用程序. 2.双击打开"Program.cs"文件,编写代码如下所示: 1 using System; 2 using Sys

java多线程、线程池的实现

Java实现多线程的3种方法:继承Thread类.实现runnable接口.使用ExecutorService,Callable.Future实现有返回值的多线程.前2种线程的实现方式没有返回值,第三种实现方式可以获取线程执行的返回值. 一:继承java.lang.Thread类 public class MyThread extends Thread { @Override public void run() { System.out.println( "my thread begin.&qu

Linux下简单的多线程编程--线程池的实现

/* 写在前面的话: 今天刚“开原”,选择了一篇关于线程池的文件与大家分享,希望能对您学习有所帮助,也希望能与大家共同学习! 选择在这个特殊的时候注册并发文章也是有一些我个人特殊的意义的,看我的id(西游小学生.45)就知道了,哈哈.在这里也很感谢博客园的员工,刚发申请两分钟就同意了. */ 最近由于要写一个类似于QQ的程序,所以想到要用到多线程.既然要用多线程,那何不写一个线程池?于是上网搜了搜多线程的代码,发现大多都不是很完善,或者有些小bug.所以,在这里贴出一个完整的,经过我多重测试的,

多线程和线程池

有这样一个需求:你有一个list集合,需要使用该集合作为参数,调用另一个系统并返回结果后处理它(主要的目的是处理结果) 解决方案:用线程池,不关闭线程池,将多个线程放入一个List集合中,使用invokeAll方法,相当于是将多个线程打包执行,统一返回,这样线程池可以一直不关闭,不用为了一个list开一个线程池,并且多个线程打包调用不会造成和其他用户的多线程冲突(究竟是你的线程还是我的线程). ExecutorService cachedThreadPool = Executors.newCac

java 多线程和线程池

● 多线程 多线程的概念很好理解就是多条线程同时存在,但要用好多线程确不容易,涉及到多线程间通信,多线程共用一个资源等诸多问题. 使用多线程的优缺点: 优点: 1)适当的提高程序的执行效率(多个线程同时执行). 2)适当的提高了资源利用率(CPU.内存等). 缺点: 1)占用一定的内存空间. 2)线程越多CPU的调度开销越大. 3)程序的复杂度会上升. 对于多线程的示例代码感兴趣的可以自己写Demo啦,去运行体会,下面我主要列出一些多线程的技术点. synchronized 同步块大家都比较熟悉

Android多线程操作——线程池管理综述

题记-- 难过了,悄悄走一走: 伤心了,默默睡一觉: 优雅不是训练出来的,而是一种阅历: 淡然不是伪装出来的,而是一种沉淀: 时间飞逝,老去的只是我们的容颜: 时间仿佛一颗灵魂,越来越动人: 1.简述: 在多线程的世界中,是那么的神奇 与 高效以及合理: 2.创建线程池实例 官方推荐使用Executors类工厂方法来创建线程池管理,Executors类是官方提供的一个工厂类,里面封装了好多功能不一样的线程池,从而使得我们创建线程池非常的简单:                    3.使用线程池

C#多线程和线程池

1.概念  1.0 线程的和进程的关系以及优缺点 windows系统是一个多线程的操作系统.一个程序至少有一个进程,一个进程至少有一个线程.进程是线程的容器,一个C#客户端程序开始于一个单独的线程,CLR(公共语言运行库)为该进程创建了一个线程,该线程称为主线程.例如当我们创建一个C#控制台程序,程序的入口是Main()函数,Main()函数是始于一个主线程的.它的功能主要 是产生新的线程和执行程序.C#是一门支持多线程的编程语言,通过Thread类创建子线程,引入using System.Th