JAVA或C#中Thread.Sleep()的使用

来源:互联网 发布:scrapy windows教程 编辑:程序博客网 时间:2024/06/05 09:24

JAVA或C#中Thread.Sleep()的使用

在使用C#写界面的过程中,一直有个疑问,线程的执行时间分配机制是如何的?Thread.Sleep()的实现原理是什么?
直到看到了这一篇参考文章,这篇文章形象的解释了Unix和Windows下的线程时间分配机制,并介绍了Thread.Sleep()的原理。

下面是我自己的学习总结,以便于以后查看。

  • Unix和Windows下的时间分配机制
    Unix:CPU使用时间片算法给进程分配时间,所有进程排成一个队列,CPU按顺序给每个进程分配时间,当某一个进程的时间片结束后还在运行,CPU会挂起该进程,并执行下一个进程。如果时间片结束前进程就阻塞或者结束了,CPU会立即执行下一个进程。每个用完时间片的进程会移动到队列的最后一位。
    Windows:CPU时间分配属于抢占式,当某个进程获得CPU时间,除非自己退出,则会霸占CPU时间。此时CPU是默认每个进程会自动退出的。每一个进程均有一个优先级,饥饿程度和总优先级,总优先级由进程本身的优先级和饥饿程度决定,进程越久没有获得CPU时间,其饥饿程度就会越高。CPU的执行时间由诸多进程竞争得到,每次竞争时的总优先级最高的进程获得CPU时间。在当前执行进程挂起或退出时,会触发竞争
    举个例子,还是使用参考文章里面的例子:
    假设有源源不断的蛋糕(CPU时间),一副刀叉(一个CPU),十个吃蛋糕的人(十个进程)。
    在Unix下会有这样的情况:CPU告诉每个人(进程),你们每个人只有1分钟的时间吃蛋糕,排着队来吃,吃完的人后面去排着队接着吃。所以这种情况下每个都是固定的1分钟时间来吃蛋糕。当然也有这样的情况,某个人吃了30秒吃饱了,然后他就会说我吃饱了(挂起),CPU就会让下一个人来吃。
    而在Windows下情况则不同了:CPU说你们每个人有个优先级、饥饿程度,我会按照这些给你们排个总优先级,总优先级最高的来吃蛋糕,吃到你不想吃为止。所以就会有这样的情况,某个人是MM,那她的优先级就高,因此总优先级就高,如果她的总优先级最高,那她就会来吃蛋糕,当她吃饱了的时候,她就会说我吃饱了(挂起)。那CPU就会说你们现在再来比一比总优先级,此时MM因为吃了蛋糕,饥饿程度变低了,总优先级就降低了,其他人没吃到蛋糕,饥饿程度增加,总优先级也增加了。但是此时有两种情况,第一种情况是MM的总优先级不是最高了,当然就由别人去吃蛋糕了,第二种情况是MM的总优先级依然是最高的,那这次竞争过后还是MM去吃蛋糕,这下MM不乐意了,我都吃饱了怎么还吃啊。所以第二种情况就要用到Thread.Sleep()了。
  • Thread.Sleep()的作用和使用
    Thread.Sleep()这个方法的作用是告诉CPU,在以后一段时间内我不参与竞争。比如Thread.Sleep(1000)就是说在以后的1S内,如果有竞争的话,不会把该进程算进来。
    所以在上面的场景中,当MM吃饱了过后,为了避免下次竞争再次获得吃蛋糕的机会,吃太多蛋糕吃胖了自己,那她就可以告诉CPU,在后面的一小时内我不想吃蛋糕了(Thread.Sleep()),那么在后面一小时内,MM都不会参与竞争。那么在准确的一小时后,MM能不能准时再吃到蛋糕呢?这个答案是不确定的,因为在一小时后,可能别人正在吃蛋糕,还没有竞争开始,因此MM只能先等着别人吃饱(挂起);也有可能在一小时后,刚好别人吃饱了,又要竞争了,但是MM的总优先级此时不是最高的,因此没有获得吃蛋糕的机会,MM还是要等待;当然最后一种可能就是,一小时后刚好有竞争,MM的总优先级又是最高的,那MM就能顺利的吃到蛋糕了。
    还有一个问题就是,Thread.Sleep(0)的使用有没有必要。
    这个答案是肯定的,有Thread.Sleep(0)和没有是有很大区别的。
    假设一个MM很善良,吃蛋糕的时候想,其他人没吃到蛋糕太可怜了,让其他人来吃吧,那她就告诉CPU:我们再来竞争一下吧,CPU说:不行,没有这种操作!
    所以她只好换一种说法:在未来0毫秒内我不参与竞争(Thread.Sleep(0))
    此时,CPU就会说:好吧,我们来比一下总优先级吧!
    注意,此时MM也是参与竞争的,因为0毫秒已经过去了!
    因此,Thread.Sleep(0)的作用就是触发操作系统立刻重新开始一次竞争!
    另外,虽然上面提到说“除非自己退出,则会霸占CPU时间”。但这个行为仍然是受到制约的——操作系统会监控你霸占CPU的情况,如果发现某个线程长时间霸占CPU,会强制使这个线程挂起。
原创粉丝点击