threadpoolmanager_threadlocal是线程安全的吗

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

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【Python秒杀脚本】淘宝或京东等秒杀抢购

    【Python秒杀脚本】淘宝或京东等秒杀抢购提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、环境二、安装1.ChromeDriver安装2.Seleuinm安装3.淘宝秒杀脚本4.京东秒杀脚本总结前言提示:这里可以添加本文要记录的大概内容:我们的目标是秒杀淘宝或京东等的订单,这里面有几个关键点,首先需要登录淘宝或京东,其次你需要准备好订单,最后要在指定时间快速提交订单。这里就要用到一个爬虫利器Selenium,Selenium是一个用于Web应用程序测试的工具,Selenium可以直接运行在浏览器中,通.

    2022年5月7日
    49
  • 怎么安装pandas库_python第三方库pandas

    怎么安装pandas库_python第三方库pandas问题现象:PyCharm中运行程序,报错,提示“ModuleNotFoundError:Nomodulenamed’pandas’”第一种方法:1.电脑WIN+R,输入cmd,输入pipinstallpandas,等待下载完成即可。2.如果有以下提示,说明pip的版本可能不一致,需要解决冲突。想更新pip,输入pipinstall–upgradepip,报错,提示“Nomodulenamedpip”3.解决方法,输入python-mensu

    2022年8月29日
    6
  • StringTokenizer类的用法「建议收藏」

    StringTokenizer类的用法「建议收藏」StringTokenizer是一个用来分隔String的应用类,相当于VB的split函数。1.构造函数publicStringTokenizer(Stringstr)publicStringTokenizer(Stringstr,Stringdelim)publicStringTokenizer(Stringstr,Stringdelim,boolean

    2022年8月11日
    8
  • 国税总局发票查验平台验证码识别方案,识别率达98%「建议收藏」

    国税总局发票查验平台验证码识别方案,识别率达98%「建议收藏」这是一篇含金量很高的干货文章,国家税务总局全国增值税发票查验平台验证码识别方案和具体思路,实验结果测试了200+次,识别率达到98%以上,识别速度的话,CPU大概5-8毫秒左右,模型大概3mb。

    2022年7月17日
    25
  • apache安装ssl证书_apache ssl证书配置

    apache安装ssl证书_apache ssl证书配置1、apache错误提示libz.a:couldnotreadsymbols:Badvalue”重新安装openssl加上-fPIC和enable-shared参数./config-fPIC–prefix=/usr/local/openssl1.0.1 enable-shared2、apache的httpd.conf缺乏LoadModulessl_module

    2025年11月30日
    6
  • JS setTimeout和setInterval的区别

    JS setTimeout和setInterval的区别1 setTimeout 和 setInterval 都属于 JS 中的定时器 可以规定延迟时间再执行某个操作 不同的是 setTimeout 在规定时间后执行完某个操作就停止了 而 setInterval 则可以一直循环下去 functionfun alert hello setTimeout fun 1000 参数是函数名 setTimeout fun 1000

    2025年11月21日
    5

发表回复

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

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