为什么要放弃使用Thread.Sleep

前言

此文并不是说要完全放弃使用Thread.Sleep,而是要说明在符合哪些情况下使用!

场景

很多时候,我们会需要一个定时服务来处理业务。

但并不是死死的每隔N分钟执行一次那种,而是在一次处理完后,算好下一次处理的时间点。

当到达此时间点,触发程序重新开始执行代码。

普遍做法

  

普遍的情况下,都是使用while(true){Thread.Sleep()}来实现,废话不多话,看代码版本1:

class Program
    {
        static void Main(string[] args)
        {
            var workLists = new List<string>() { "任务1", "任务2", "任务3", "任务4" };
            foreach (var task in workLists)
            {
                var thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Work.DoWork));
                thread.Start(task);
            }
        }
    }
class Work
    {
        public static void DoWork(object target)
        {
            var taskType = target as string;
            var interval = 1 * 60 * 1000;//处理失败,1分钟后重试
            var maxTimes = 5;
            var retryTimes = 0;
            while (true)
            {
                while (retryTimes < maxTimes)
                {
                    var ok = Proccess(taskType);
                    if (ok)
                    {
                        retryTimes = maxTimes;
                    }
                    else
                    {
                        retryTimes++;
                        System.Threading.Thread.Sleep(interval);
                    }
                }

                var tim = GetTotalMillisecondsForNext();//计算离下一次开始处理的时间
                System.Threading.Thread.Sleep(tim);//挂起一段时间后,重新唤醒
                retryTimes = 0;
            }
        }

        private static bool Proccess(string taskType)
        {
            Console.WriteLine("开始执行处理:{0}", taskType);
            return true;
        }

        private static int GetTotalMillisecondsForNext()
        {
            //这里根据自己的业务来决定
            return 2 * 1000;
        }
    }

代码简单易懂。

分析

版本1中,循环强制创建线程,并使用System.Threading.Thread.Sleep(tim)来挂起线程,然后重新唤醒。

这种方式不好之处在于:占用系统线程资源,是一种浪费。如同占着茅坑不拉屎!线程是一种十分宝贵的资源,创建,销毁,切换 都是相当耗性能的。

当Sleep的时候,就等于说:现在我不用,但是你也别想用。你要用?自己去Create一个。

有的人说,Sleep的时候 不占用CPU啊!对,是不占用CPU ,但是占着线程资源,阻碍系统的线程调度!

可以参考下这文章

Threads are a limited resource, they take approximately 200,000 cycles to create and about 100,000 cycles to destroy. By default they reserve 1 megabyte of virtual memory for its stack and use 2,000-8,000 cycles for each context switch. This makes any waiting thread a huge waste.

改进

  使用System.Timers.Timer来改进我们的程序。当执行处理业务的代码时,首先把timer停止,处理完毕后,算好一次执行的时间点,赋给timer并启动,看代码版本2

class Program
    {
        static void Main(string[] args)
        {
            var workLists = new List<string>() { "任务1", "任务2", "任务3", "任务4" };

            Parallel.ForEach(workLists,
                new ParallelOptions() { MaxDegreeOfParallelism = 3 },
                (task) => { new Work2() { TaskType = task }.DoWork(); });

            Console.ReadLine();
        }

    }
 class Work2
    {
        private Timer _workTimer;
        public string TaskType { get; set; }
        public void DoWork()
        {

            _workTimer = new System.Timers.Timer();
            _workTimer.Interval = 1000;
            _workTimer.Elapsed += new ElapsedEventHandler(TimerHanlder);
            _workTimer.Start();
        }

        private void TimerHanlder(object sender, ElapsedEventArgs e)
        {
            _workTimer.Stop();

            var interval = 1 * 60 * 1000;//处理失败,1分钟后重试
            var maxTimes = 5;
            var retryTimes = 0;

            while (retryTimes < maxTimes)
            {
                var ok = Proccess();
                if (ok)
                {
                    retryTimes = maxTimes;
                }
                else
                {
                    retryTimes++;
                    System.Threading.Thread.Sleep(interval);
                }

            }

            var times = GetTotalSecondsForNext();
            Console.WriteLine("{0}秒后重新执行", times);
            _workTimer.Interval = times * 1000;//计算离下一次开始处理的时间
            _workTimer.Start();

        }

        private bool Proccess()
        {
            Console.WriteLine("开始执行处理:{0}", TaskType);
            return true;
        }

        private int GetTotalSecondsForNext()
        {
            //这里根据自己的业务来决定
            return 3;
        }
    }

特别说明一下:Main方法中的Console.ReadLine();很重要,让主线程处于等待的状态,子线程就可以一直执行下去不中断

总结

1:使用Task,而不是使用new System.Threading.Thread。是否要创建线程,应该让系统来决定,利用可复用资源

2: System.Threading.Thread.Sleep(interval);只合适在 "有限度的 " 循环场景中,比如 最多重试N次、倒计时等等

如果不对之处,请各位斧正!

时间: 2024-10-10 02:33:04

为什么要放弃使用Thread.Sleep的相关文章

维护项目的敏捷转型

现在敏捷已经是IT行业的开发的行业标准了,大部分公司在产品开发中都采用的敏捷来解决一些由瀑布模型带来的问题. 敏捷的迭代周期短,每个迭代都有预设目标,而且每个迭代都有相应的产出,能大大地提高项目相关人的满意度. 产品开发的一个典型周期是: 需求澄清->开发->测试->发布->维护. 而当产品成熟后,新的功能和改进将会越来越少,同时维护和客户支持的工作量则会越来越大.维护则包括:技术支持.项目管理.工程维护.版本管理. 对于成熟的组织来说,瀑布模型是所有根据客户的要求进行的维护活动(

硬币语录

看来你我的操作系统还有对短线的理解都不太一样,我在帖子的开篇就讲了这个账户的操作思路以及理由,这个账户所谓的短线不是为了短而短的,甚至不是时间定义上的长短,而是相对于我的‘长线票’而言的,所以我根本没有约束过我短线票的时间周期,因此我在开篇的时候也说了这个账户即使是短线仓位原则上我也不会割肉的.因为对我来说我只需要做到刀刀见血这个市场就对我造成不了实质性伤害,我在刀刀见血的前提下逐步提高我单位时间内的盈利占比,这是我在这个充满了不确定性的市场中知道的少有的一点确定性的东西,我为什么要放弃这点确定

华为前员工:我在华为敲代码知道的事(转载)

作为一名前华为程序猿,最近经常有小伙伴问我说为什么要放弃一份看起来高大上的前沿科技工作,我在当面自然都义正言辞地表态说因为我深爱着现在的工作,(大义凛然状)想在这里干一番大事业!其实静下心来想想,不免有一些感触和心里的话,正好借这个机会说出来,以飨读者,也顺便纪念那一段逝去的时光. 要说华为公司的一个显著优势,自然就是高收入了.在 5 月初的一期<财经郎眼>节目中,郎咸平教授曾披露,一个在华为公司工作 7 年的普通员工,年薪可以拿到 18 万,奖金 35 万,分红 13 万,年收入一共在 66

测试人员的误区:迷信自动化(转)

终于有时间总结一下过去几年在微软的测试经验,谈谈对测试自动化的看法. 先说说为什么做测试的人喜欢搞自动化. 第一,自尊心.计算机科班出身的人都喜欢作开发(Dev).做测试工作经常是身不由己,可是测试工作很多时间不需要编程,于是做测试的人想方设法写些程序,以显示自己也会编程.结果往往是欲罢不能,测试自动化程序越写越多,越写越复杂.后面我会谈谈测试自动化框架复杂的代价. 第二,为了出成绩.很多测试组为了向管理层展示成绩,往往要拿出例如测试自动化达到80%,程序覆盖率达到90%.要我说,这些都是Bul

任正非:华为要树立一些黄继光式榜样,不作为就末位淘汰(只有正规军有使命感和责任感驱使他能长期作战)

集微网 6月21日报道 今日,华为官方论坛心声社区微信又放出老板任正非的最新讲话内容.其主要探讨什么叫精神文明,什么叫物质文明? 任正非表示,华为就是要树立出一些榜样来,人人都想做黄继光.人人想立功受奖,这才是我们的优势啊,人人都不讲贡献,那还有啥优势呢?人人都只守规矩,那我们不如去办幼儿园,幼儿园孩子是最守规矩的,但什么都不懂就没有贡献,我们是以贡献为中心来树立榜样的. 任正非还称,对不作为.胡乱作为.不能作为.假作为的干部要末位淘汰.以激活正能量,这就是精神文明. 另外,任正非还透露,在未来

你们为什么自称野草助力微营销团队?

我们之所以自称野草助力微营销团队,这其中有什么含义呢? 连云港野草文化传媒有限公司里的<野草>创作灵感来自唐代三大诗人之一白居易<赋得古原草送别>中的诗句:"野火烧不尽,春风吹又生."意思是:不管烈火怎样无情地焚烧,只要春风一吹,又是遍地青青的野草,极为形象生动地表现了野草顽强的生命力.我们公司之所以又自称野草助力微营销团队,是为了让客户明白野草的真实性和持续性,没有任何灾难可以阻止野草团队顽强茁壮成长 那么我们公司的教程为什么叫做<野草助力微营销>

GXUI 的认识

GXUI 是 Google 内部的一些编程极客,出品的一个跨平台 的 UI 库,它给出了一个UI框架.使我们有机会利用GO语言,来建立界面丰富的应用程序.摆脱黑糊糊的命令行程序.对于这个实验性质的UI库的前途来说,可谓是极其艰难.因为,编写GXUI的几个极客不幸的提出,由于时间有限,不想浪费到这个项目中,不会再进行维护(Unfortunately due to a shortage of hours in a day, GXUI is no longer maintained.)!可以说,这个U

绩效考核是洋垃圾?

绩效考核成功吗?根据蒂莫西.谢尔哈特(TimothySchellhardt)在<华尔街日报>(1996年11约9日)的报告:九成以上的绩效考核制并不成功.彼得.斯科尔特斯(PeterScholtes)怀疑实际上比这更糟. 一.目标管理绩效考核的鼻祖德鲁克在美国倍受指责 1.日本(戴明)式和美国(目标)式管理在1980年代决出了胜负 1940年代,戴明等人对美国战争产业教授统计过程控制学(SPC–Statistical Process Control). 1950年代,统计过程控制学及其人群关系

由于好高骛远所以半途而废(张作作)

昨晚跟一位已经奋斗在工作岗位的朋友聊天,他总是一再表示羡慕还处在学生时代的我.我却恨不得挖出一颗赤诚的红心告诉他,我每天被看不完的书和写不完的论文压的喝口水都要喘半天.我才羡慕每天为生活奋斗而领着薪水的他. 后来他说,我给你讲个笑话,我从小都以为全国仅仅有清华和北大两所学校,小学升初中的时候.我一直纠结要去上清华还是去上北大,直到初中开学那天我妈带我去城西的一所学校报道,我才知道原来中国是有三所学校的. 我听完笑的简直不能理喻,问他,然后呢? 他说,后来越上学越发现.原来全国有300所学校都不止