自己做淘客网站成本大吗,徐州市网站开发,网页设计网站免费,优秀的网页设计图片一、理论分析
回答这个要先从线程时间精度#xff08;时间片#xff09;开始说起。很多参考书说#xff0c;默认情况下#xff0c;时间片为15ms 左右#xff0c;但是这是已经过时的知识。在老的 Windows 操作系统里#xff0c;应用程序模式时时间片 15ms 左右#xff0…一、理论分析
回答这个要先从线程时间精度时间片开始说起。很多参考书说默认情况下时间片为15ms 左右但是这是已经过时的知识。在老的 Windows 操作系统里应用程序模式时时间片 15ms 左右准确一点是15.625 左右。服务器模式是其双倍。但是在微软推行.Net 普及 Task之后规则已经改动并且做了精细的调节。现在Win10的时间精度为1ms(不用担心谷歌浏览器修改时间精度了)Win2013服务器的时间精度为7ms使用微软提供的测试工具可以测出来ClockRes - Sysinternals | Microsoft Learn 命令行powercfg /energy
我们可以通过它可以更直观的看出 因为有这个请求在所以无论如何最低的计时器分辨率都只能为1ms。
所以现在Win10 默认状态下Sleep(1) 占时不再是15ms而是1ms 左右 1120us 即 1.12ms
下面现在正式回答Thread.Sleep(0)Thread.Yield()Thread.Sleep(1) 有什么不同首先Thread.Sleep 只是放弃时间片的剩余时间让系统重新选择调度一个合适的线程其优先级等于或者高于当前线程。在没有其他活动线程的情况下使用Sleep(0) 还是选上原来线程即连任如果连任了系统不会对其做上下文切换所以有 由上面的图片可知耗时为18us左右即0.018ms
其次Thread.Yield() 是什么呢跟 Thread.Sleep 有点像但是它跟 Thread.Sleep(0) 有点区别系统选择继任时可以选择优先级比原来低的线程。最后Thread.Sleep(1) 是什么情况呢前面说了Thread.Sleep(0) 只是放弃时间片的剩余时间让系统重新选择调度一个合适的线程。但是 Thread.Sleep(1) 却让当前线程沉睡了即使只有1ms 。也就是说主动放弃下次竞选所以不可能连任系统上下文必然发生切换(优先级低于原线程的家伙也有机会)。
二、最后总结一下Sleep(0)的用途
1在图形界面程序中使用Thread.sleep(0)可以避免长时间运行的任务阻塞UI线程的执行。例如在GUI程序中当用户通过按钮点击或其他事件触发某个任务时在该任务完成前可能需要等待某个数据加载、文件下载或其他操作完成。如果不使用Thread.sleep(0)就可能导致主线程阻塞而导致程序无响应。
2在多线程爬虫程序中使用Thread.sleep(0)可以有效地限制连接网站的频率避免过于频繁访问同一目标网站而被封禁IP。例如在高并发情况下为了提高效率某些爬虫程序会采用多线程方式进行网站抓取这样往往需要控制每个线程之间的请求频率以避免对目标网站造成负担或被视作恶意攻击。
3在多线程程序中使用Thread.sleep(0)可以优化线程调度算法使得程序更加平滑和高效。例如在Java Web应用中Tomcat服务器等Web容器采用线程池来管理客户端请求。为了避免某些线程占用关键资源导致其他线程无法响应可以使用Thread.sleep(0)控制每个线程之间的竞争性使得整个程序稳定、流畅地运行。
三、效率方面影响
Thread.Sleep(N)会严重影响当前线程中循环的运行效率原因上面已经说明的很清楚了上下文切换线程竞争所以在高速定时器的应用中
1、Timer的Period小于10ms精度会很差Timer不能满足精度要求在高速定时器中不推荐用Timer
Timer timer new Timer(TimerCallback, null, 0, 2);
timer.Change(0, 2);long times 0;
void TimerCallback(object sender)
{times;Thread.Sleep(1);
}
运行一分钟后的结果3767远低于1000/2*6030000
2、用for循环实现Timer的功能不管是Task.Delay还是Thread.Sleep都实现不了小于10ms100HZ的精度
1) 使用 Task.Delay 和 async/await对于10ms以下精度不够
Delay(TimeSpan.FromMilliseconds(2), null);public async Task Delay(TimeSpan interval, FuncTask func)
{while (true){await Task.Delay(interval);times;}
}
运行一分钟后的结果3729远低于1000/2*6030000
2使用 Thread.Sleep精度稍微好些但是不够
DelaySleep();public async Task DelaySleep()
{Task.Run(() {while (true){Thread.Sleep(2);times;}});
}
运行一分钟后的结果19599还是低于1000/2*6030000
3、解决思路Timer大时间里面写循环
DelayLoop(TimeSpan.FromMilliseconds(1000), func);public async Task DelayLoop(TimeSpan interval, Action func)
{while (true){await Task.Delay(interval);func();}
}private void func()
{for(int imm 0; imm500; imm){Thread.Sleep(0);lock (this){times;}}
}
运行一分钟后的结果29000稍微低于1000/2*6030000由于是手动一分钟后点击没有写成一分钟自动停止所以存在误差有兴趣的同学可以测试下可以满足高速定时器功能已在项目中使用 参考资料
1、(43 封私信) C# Thread.Sleep(0)有什么用 - 知乎 (zhihu.com)
2、https://blog.csdn.net/weixin_73077810/article/details/130519033
--以上。