博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ThreadPool.QueueUserWorkItem的性能问题
阅读量:6911 次
发布时间:2019-06-27

本文共 3439 字,大约阅读时间需要 11 分钟。

在WEB开发中,为了降低页面等待时间提高用户体验,我们往往会把一些浪费时间的操作放到新线程中在后台执行。

简单的实现代码就是:

//代码一new Thread(()=>{//do something}).Start();
可是对于一个请求量大的网址这样做是非常不现实的——每个操作都要开启一个新线程,终于会因CPU不堪重负而使站点挂掉。

更好的做法是使用线程队列。

对于线程队列  非常多人应该都不陌生,下边看微软的解释:

将方法排入队列以便运行,并指定包括该方法所用数据的对象。此方法在有线程池线程变得可用时运行。

它的作用就是将一些操作放入当前线程之外的另外一个线程中运行,它的用法非常easy:

//代码二ThreadPool.QueueUserWorkItem(stat => {//do something}, null);

它相对代码一的长处是会利用已经创建过的空暇的线程,假设没有空暇就排队,而不会盲目的一直创建下去。

可是它并没有摆脱“创建新线程”的问题:过多的线程会占用很多其它的资源。由此我们不难想到,我们为什么不自己搞个队列,让它们在同一个线程中逐个运行?对此,我写了个简单的实现类:

public class BackgroundTasks    {        private class TaskEntity        {            public TaskEntity(Action func, object data)            {                this.Function = func;                this.Data = data;            }            public Action Function;            public object Data;        }        static Queue
list = new Queue
(); static BackgroundTasks() { Thread th = new Thread(RunTask); th.IsBackground = true; th.Start(); } static void RunTask() { while (true) { if (list.Count==0) { Thread.Sleep(1000); } else { TaskEntity entity; lock (list) { entity = list.Dequeue(); } try { entity.Function(entity.Data); } catch { } Thread.Sleep(10); } } } public static void Add(Action
func, object data) { lock (list) { list.Enqueue(new TaskEntity(func, data)); } } }
该类的使用非常easy:

BackgroundTasks.Add((obj)=>{

Console.WriteLine("这个任务的加入时间是:{0}", obj as DateTime);

}, DateTime.Now);

另一个“实例版”的,就是针对每一个方法,分别创建一个任务队列:

public class BackgroundTasks
{ private Action
Function; private Queue
list = new Queue
(); public BackgroundTasks(Action
func) { this.Function = func; Thread th = new Thread(RunTask); th.IsBackground = true; th.Start(); } private void RunTask() { while (true) { if (list.Count == 0) { Thread.Sleep(1000); } else { T data; lock (list) { data = list.Dequeue(); } try { Function(data); } catch { } Thread.Sleep(10); } } } public void Add(T data) { lock (list) { list.Enqueue(data); } } }
调用演示样例:

var bg = new BackgroundTasks
((blog) => { Console.WriteLine(blog.BlogId); });int i = 0;while (i++ < 1000){ bg.Add(new Blog() { BlogId = i });}

这个设计既攻克了异步运行,又攻克了占用资源的问题。

可是世界上没有完美的东西,代码也是如此,因为队列中的任务是单线程运行,可能会导致某些任务在非常长时间后才会被运行到,或者重新启动IIS导致非常多任务还没有被运行就被丢弃。

不管怎么,这样的设计还是适用于非常多“普通情况”。

转载地址:http://zqncl.baihongyu.com/

你可能感兴趣的文章
基本类型和装箱基本类型的区别
查看>>
剑指offer题目java实现
查看>>
ThreadLocal
查看>>
抽象工厂类--一个简单的例子
查看>>
配置toad远程连接oracle
查看>>
028 Partitioner:数据分区器
查看>>
移位实现正负数原码输出
查看>>
阿里云端口失效导致tomcat无法对外提供服务
查看>>
如何在Android Studio中指定NDK位置?
查看>>
更改Android应用程序的图标
查看>>
连载:面向对象葵花宝典:思想、技巧与实践(35) - NOP原则
查看>>
Redis(五)-- Java API
查看>>
Android中使用OnClickListener接口实现button点击的低级失误
查看>>
python核心编程——python对象
查看>>
我第一家互联网公司产品开发周期
查看>>
指数函数及其性质教学设计
查看>>
关于内存中栈和堆的区别(非数据结构中的堆和栈,区别)【转】
查看>>
嵌套查询
查看>>
HTML5即将迎来黄金时代 轻应用再成行业焦点
查看>>
python-Levenshtein几个计算字串相似度的函数解析
查看>>