昨天反编译看了公司项目首席架构师实现的线程池。非常之惊讶,在没有.net 4可用的年代。那思想和那技术是相当的可以啊。佩服。

这里说的线程池是一个类我总觉得这样叫有点不名副其实。其实就是一个类内部实现了FIFO队列,把临时数据放到这个队列里,“线程池类”按照入队的先后次序触发一个负责解析校验等的事件,并且把数据传递个这个事件。

好了,上代码:

    /// <summary>/// 自定义线程池类,不依赖.net Queue实现了先进先出处理队列里数据/// </summary>public class CoreThreadPool : IDisposable{/// <summary>/// 队列元素申明/// </summary>[StructLayout(LayoutKind.Sequential)]private class PoolData{/// <summary>/// 外部要求放入队列的数据/// </summary>public object Data;/// <summary>/// 需要执行的命令(Exit/Command(自定义))/// </summary>public CoreThreadPool.PoolCommand Command;public PoolData(){this.Command = CoreThreadPool.PoolCommand.Exit;}public PoolData(object data){this.Data = data;this.Command = CoreThreadPool.PoolCommand.Command;}public PoolData(CoreThreadPool.PoolCommand cmd){this.Command = cmd;}}protected enum PoolCommand{Command,Exit}protected SafeFileHandle complatePort;/// <summary>/// 线程池主线程/// </summary>protected Thread thread;protected volatile bool isOpened;[method: CompilerGenerated][CompilerGenerated]public event Action<object> Exceute;[method: CompilerGenerated][CompilerGenerated]public event Action<object> ExitExceute;/// <summary>/// 线程池是否正在运行/// </summary>public bool IsOpened{get{return this.isOpened;}set{this.isOpened = value;}}[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]private static extern SafeFileHandle CreateIoCompletionPort(IntPtr FileHandle, IntPtr ExistingCompletionPort, IntPtr CompletionKey, uint NumberOfConcurrentThreads);[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]private static extern bool GetQueuedCompletionStatus(SafeFileHandle CompletionPort, out uint lpNumberOfBytesTransferred, out IntPtr lpCompletionKey, out IntPtr lpOverlapped, uint dwMilliseconds);[DllImport("Kernel32", CharSet = CharSet.Auto)]private static extern bool PostQueuedCompletionStatus(SafeFileHandle CompletionPort, uint dwNumberOfBytesTransferred, IntPtr dwCompletionKey, IntPtr lpOverlapped);/// <summary>/// 启动线程池的主线程/// </summary>public void Start(){isOpened = true;if (thread != null){throw new Exception("线程池已经是启动状态!");}complatePort = CreateIoCompletionPort(new IntPtr(-1), IntPtr.Zero, IntPtr.Zero, 0u);if (complatePort.IsInvalid){throw new Exception(string.Format("创建IOCP出错!原因是:{0}", Marshal.GetLastWin32Error().ToString()));}thread = new Thread(new ParameterizedThreadStart(this.Run));thread.Start(complatePort);}/// <summary>/// 外部提交数据对象到队列/// </summary>/// <param name="data"></param>public void Post(object data){PostData(new CoreThreadPool.PoolData(data));}/// <summary>/// 线程池主线程执行逻辑/// </summary>/// <param name="CompletionPortID"></param>private void Run(object CompletionPortID){SafeFileHandle completionPort = (SafeFileHandle)CompletionPortID;            while (IsOpened){uint num;IntPtr intPtr;IntPtr value;//从队列里取出最前面的对象CoreThreadPool.GetQueuedCompletionStatus(completionPort, out num, out intPtr, out value, 4294967295u);if (num > 0u){GCHandle gCHandle = GCHandle.FromIntPtr(value);CoreThreadPool.PoolData poolData = (CoreThreadPool.PoolData)gCHandle.Target;gCHandle.Free();if (poolData.Command != CoreThreadPool.PoolCommand.Command){IsOpened = false;break;}RaiseExecute(poolData.Data);}}RaiseExitExecute("线程池已经停止。");isOpened = false;thread = null;}/// <summary>/// 触发Execute事件/// </summary>/// <param name="data"></param>private void RaiseExecute(object data){Exceute?.Invoke(data);}/// <summary>/// 触发ExitExecute事件/// </summary>/// <param name="data"></param>private void RaiseExitExecute(object data){ExitExceute?.Invoke(data);}/// <summary>/// 结束线程池主线程/// </summary>public void Stop(){PostData(new PoolData(PoolCommand.Exit));IsOpened = false;}/// <summary>/// 内部提交数据到线程池队列中/// </summary>/// <param name="data"></param>private void PostData(PoolData data){if (complatePort.IsClosed){return;}GCHandle value = GCHandle.Alloc(data);PostQueuedCompletionStatus(complatePort, (uint)IntPtr.Size, IntPtr.Zero, GCHandle.ToIntPtr(value));}public void Dispose(){if (this.thread != null && this.thread.ThreadState != System.Threading.ThreadState.Stopped){this.Stop();}}}

  代码亮点:队列是使用操作系统的,使用windows api实现的。牛吧。

由于现在项目已经依赖.net 4了。于是进行了模仿,经过一番测试,发现差不多,不过还是觉得在多线程环境下使用 ConcurrentQueue会更好些呢。

 /// <summary>/// 自定义线程池类,使用ConcurrentQueue实现了先进先出处理队列里数据/// </summary>public class CoolThreadPool<T>{protected ConcurrentQueue<T> queue = new ConcurrentQueue<T>();protected Thread thread;private volatile bool isOpened;public bool IsOpened{get{return isOpened;}}public event Action<T> Exceute;public event Action StopedExceute;/// <summary>/// 启动线程池的主线程/// </summary>public void Start(){if (thread != null){throw new Exception("线程池已经是启动状态!");}thread = new Thread(Run);thread.Start();isOpened = thread != null;}/// <summary>/// 线程池主线程执行逻辑/// </summary>private void Run(){while (isOpened){T temp;queue.TryDequeue(out temp);if (temp != null){RaiseExecute(temp);}else break;}isOpened = false;thread = null;RaiseStopedExceute();}/// <summary>/// 触发Execute事件/// </summary>/// <param name="data"></param>private void RaiseExecute(T data){Exceute?.Invoke(data);}/// <summary>/// 触发停止Execute事件/// </summary>/// <param name="data"></param>private void RaiseStopedExceute(){StopedExceute?.Invoke();}/// <summary>/// 结束线程池主线程/// </summary>public void Stop(){PostData(default(T));isOpened = false;}/// <summary>/// 外部提交数据对象到队列/// </summary>/// <param name="data"></param>public void Post(T data){PostData(data);}/// <summary>/// 内部提交数据到线程池队列中/// </summary>/// <param name="data"></param>private void PostData(T data){queue.Enqueue(data);}public void Dispose(){if (this.thread != null && this.thread.ThreadState != System.Threading.ThreadState.Stopped){this.Stop();}}}

测试代码:

string[] temp = new string[]{"This is 1.","This is 2.","This is 3.","This is 4.","This is 5.","This is 6.","This is 7.","This is 8.","This is 9.","This is 10.","This is 11.","This is 12."};pool.Exceute += Pool_Exceute1;pool.Start();foreach (string data in temp){pool.Post(data);}

  

转载于:https://www.cnblogs.com/datacool/p/datacool_threadpool.html

自动化控制之线程池的使用相关推荐

  1. android自定义线程池工具类,妈妈再也不用担心你不会使用线程池了(ThreadUtils)...

    为什么要用线程池 使用线程池管理线程有如下优点:降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可 ...

  2. Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

    为什么80%的码农都做不了架构师?>>>    这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情.并发课题对于Java来说是一个又重要又难的一大块 ...

  3. 不恰当使用线程池处理 MQ 消息引起的故障

    现状 业务部门反应网站访问特别慢,负责运维监控的同事说MQ消息队列积压了,中间件的说应用服务器内存占用很高,GC 一直回收不了内存,GC 线程占了近 100% 的 CPU,其他的基本上都在等待,数据库 ...

  4. 推荐一个强大的开源动态线程池项目

    今天和大家分享的是一个动态线程池,Hippo4J Hippo4J,是一个基于美团动态线程池的设计理念,针对该类线程池,在一般的基础上增强了动态调参.监控.报警等功能的一个版本. Hippo4J可以通过 ...

  5. Python爬虫——使用线程池爬取同程旅行景点数据并做数据可视化

    大家好!我是霖hero 正所谓:有朋自远方来,不亦乐乎?有朋友来找我们玩,是一件很快乐的事情,那么我们要尽地主之谊,好好带朋友去玩耍!那么问题来了,什么时候去哪里玩最好呢,哪里玩的地方最多呢? 今天将 ...

  6. 线程池与Android的日日夜夜

    线程池与Android的日日夜夜 假如你Java中研究到了线程池的话,一般来说,你已经对线程的原理颇有研究了,或者说,你意识到了线程的某些瓶颈或者缺点.你说,要有光,所以,天降线程池. 正儿八经的说, ...

  7. java多线程及线程池使用

    Java多线程及线程池的使用 Java多线程 一.Java多线程涉及的包和类 二.Java创建多线程的方式 三.Java线程池 1. 创建线程池ThreadPoolExecutor的7个参数 2. 线 ...

  8. DirectX12(D3D12)基础教程(十六)——实现渲染线程池:3个内核同步对象实现渲染线程池/大规模线程池

    文章目录 1.前言 2.深入了解MsgWaitForMultipleObjects()函数fWaitAll参数为TRUE时的问题 3.内核同步对象:CPU线程屏障(CPU Barrier)基础知识 4 ...

  9. mysql 线程池大小设置_MySQL线程池参数解析

    线程池是数据库系统非常重要功能,然而MySQL社区版并不包含线程池功能,不过好在MySQL的Percona发行版本提供了这个功能,除此之外,MySQL的企业版也提供线程池,从性价比上说,Percona ...

最新文章

  1. 前端学习记录 JS DOM
  2. Linux怎么确定信号来源,Linux信号来源和捕获处理以及signal函数简介
  3. rabbitmq-发布订阅模式
  4. c语言调用createthread线程的头文件_易语言API多线程总汇
  5. XShell笔记-XShell登录脚本的使用
  6. 阿里架构师必学的2019最新资料!首次公布
  7. mysql定位数据库_MySQL数据库Query性能定位
  8. 单片机毕业设计不用愁!!30篇单片机毕业设计参考案例
  9. Music-Downloader:功能强大的音乐下载器
  10. 中国男性最想娶回家的金庸女性角色排行榜zz
  11. T1-商贸宝服务无法启动解决办法
  12. 自己处理域名、主机备案流程 + 公网安备流程,总共耗时半个月左右
  13. 如何写好一篇科技论文?
  14. 2022苹果AppStore应用商店上传与APP上传流程必看(基础篇)
  15. 盛迈坤电商:电商运营要怎么样进行选款
  16. 基于滴滴云搭建安全稳定的 Memcached 服务器
  17. PHP 免费获取手机号码归属地
  18. HDU 1885 Key Task 国家压缩+搜索
  19. k8s自定义controller三部曲之二:自动生成代码
  20. 第07课:使用 HTML 5 API 创建子窗口

热门文章

  1. 架构之路--实战项目记录(二) 忘记数据库 开始抽象
  2. 东北育才 NOIP模拟赛第1场
  3. 你应该知道的计算机网络知识
  4. AlertDialog 宽度充满整个屏幕
  5. python面向对象开发(类的属性-精讲
  6. (转)WCF光芒下的Web Service
  7. 谈几个初学者混淆不清的问题
  8. linux动态线程池--原理,这儿的代码不完整
  9. 垃圾回收器机制(一):对象存活及强,弱等各种引用辨析
  10. Android merge 标签 显示错乱