threadpoolmanager_threadlocal是线程安全的吗

threadpoolmanager_threadlocal是线程安全的吗在WEB开发中,为了减少页面等待时间提高用户体验,我们往往会把一些浪费时间的操作放到新线程中在后台运行。简单的实现代码就是://代码一newThread(()=>{//dosomething}).Start();但是对于一个请求量大的网址这样做是很不现实的——每一个操作都要开启一个新线程,最终会因CPU不堪重负而使网站挂掉。更好的做法是使用线程队列。对于线程队列 ThreadPoo…


Jetbrains全系列IDE稳定放心使用

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

简单的实现代码就是:

//代码一
new Thread(()=>{
//do something
}).Start();

但是对于一个请求量大的网址这样做是很不现实的——每一个操作都要开启一个新线程,最终会因CPU不堪重负而使网站挂掉。

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

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

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


它的作用就是将一些操作放入当前线程之外的另外一个线程中执行,它的使用方法很简单:

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

它相对代码一的优点是会利用已经创建过的空闲的线程,如果没有空闲就排队,而不会盲目的一直创建下去。

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

    public class BackgroundTasks
    {
        private class TaskEntity
        {
            public TaskEntity(Action<object> func, object data)
            {
                this.Function = func;
                this.Data = data;
            }
            public Action<object> Function;
            public object Data;
        }
        static Queue<TaskEntity> list = new Queue<TaskEntity>();
        
        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<object> func, object data)
        {
            lock (list)
            {
                list.Enqueue(new TaskEntity(func, data));
            }
        }

    }

该类的使用很简单:

BackgroundTasks.Add((obj)=>{

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

}, DateTime.Now);

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

    public class BackgroundTasks<T>
    {
        private Action<T> Function;

        private Queue<T> list = new Queue<T>();

        public BackgroundTasks(Action<T> 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>((blog) => { 
    Console.WriteLine(blog.BlogId); 
});
int i = 0;
while (i++ < 1000)
{
    bg.Add(new Blog() { BlogId = i });
}

这个设计既解决了异步执行,又解决了占用资源的问题。

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

无论怎么,这种设计还是适用于很多“一般情况”。

作者:朱会震

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/189800.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • navicate 15激活码获取【2022最新】2022.02.06

    (navicate 15激活码获取)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年4月1日
  • HTML5 Canvas彩色小球碰撞运动特效

    脚本简介HTML5Canvas彩色小球碰撞运动特效是一款基于canvas加面向对象制作的运动小球动画特效。效果展示 http://hovertree.com/texiao/html5/

    2021年12月27日
  • mfc wpf winform(工业用mfc还是qt)

    编程语言的组成编程语言做为一种语言自然和英语这些自然语言有类似的地方.学英语时我们知道要先记26个字母,然后单词及其发音,接下来就是词组,句子.反正简单的说就是记单词,熟悉词法,句法.接下来就是应用了,听说读写.而使用相同语言的人大脑里都有个翻译器,可以把自己的想法翻译成语言然后用说或写表达出来,而听和读则把接收来的语言翻译成自己大脑能理解的思想.那编程语言首先也是像英语一样会制定一些单词…

    2022年4月12日
  • opencv求逆矩阵函数_c++矩阵

    opencv求逆矩阵函数_c++矩阵voidprintMatrix(CvMat*mat){intk=0;for(inti=0;irows;i++){for(intj=0;jcols;j++){printf(“%10.3f”,cvmGet(mat,i,j));

    2022年8月21日
  • matlab的length函数和size函数

    matlab的length函数和size函数在matlab中length函数和size函数的用法

    2022年5月2日
  • 石家庄职业技术学院多少分能上_石家庄职业技术学院单招录取分数线

    石家庄职业技术学院多少分能上_石家庄职业技术学院单招录取分数线本文主要介绍石家庄职业技术学院2020招生录取分数线的相关信息,对学校感兴趣,想要报考该校的同学请信息的阅读文章,若有其他有关该校的招生方面的信息可以直接咨询网站的在线老师,向他们进行咨询.一、石家庄职业技术学院招生录取分数线石家庄职业技术学院有中央财政支持高等职业学校提升专业2个,河北省示范院校重点建设专业8个(省级示范专业有重叠,合计共10个省级重点建设专业),河北省教育教学改革示范专业6个,…

    2022年9月13日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号