为什么 在循环中加入了DoEvents,cpu依然守望先锋cpu占用高100

让天下没有难学的技术
不正当使用HashMap导致cpu 100%的问题追究
不正当使用HashMap导致cpu 100%的问题追究
因最近hashmap误用引起的死循环又发生了一些案例,写了一篇blog ,看了一下,大家的分析如出一辙。这篇blog也是好几年前写的了,之前在平台技术部的博客上贴过,随着组织结构的调整,那个博客可能不再维护,把这篇文章在这儿也保存一下。
李鹏同学在blog里写了篇关于HashMap死锁模拟的文章: http://blog.csdn.net/madding/archive//5838477.aspx 做个纠正,那个不是死锁问题,而是死循环。
这个问题,我们以前讨论过。 校长之前的和淘宝的毕玄的《分布式Java应用:基础与实践》一书中都提到过 velocity导致cpu 100% 的bug,起因是HashMap的使用不当所致。
在之前的邮件列表里,校长提出过这个问题,当时我没仔细看,不清楚这个问题究竟是对 HashMap的误用,还是HashMap的潜在问题, 当时感觉不太可能是HashMap自身的问题,否则问题大了。应该是属于在并发的场景下错误的 使用了HashMap。昨天看了李鹏的blog后,觉得这个事情还是应该搞清楚一下;虽然我推测是链表形成闭环,但 没有去证明过。从网上找了一下: http://blog.csdn.net/autoinspired/archive//2662290.aspx 里面也有提到:
产生这个死循环的根源在于对一个未保护的共享变量 — 一个”HashMap”数据结构的操作。当在 所有操作的方法上加了”synchronized”后,一切恢复了正常。检查”HashMap”(Java SE 5.0)的源 码,我们发现有潜在的破坏其内部结构最终造成死循环的可能。在下面的代码中,如果我们使得 HashMap中的entries进入循环,那 么”e.next()”永远都不会为null。
不仅get()方法会这样,put()以及其他对外暴露的方法都会有这个风险,这算jvm的bug吗?应该说不是的,这个现象很早以前就报告出来了(详细见: /bugdatabase/view_bug.do?bug_id=6423457)。Sun的工程师并不认为这 是bug,而是建议在这样的场景下应用”ConcurrentHashMap”,在构建可扩展的系统时应将这点 纳入规范中。
这篇翻译提到了对HashMap的误用,但它没有点破HashMap内部结构在什么样误用情况下怎么被 破坏的;我想要一个有力的场景来弄清楚。再从李鹏的blog来看,用了2个线程来put就模拟出来了,最后堆栈是在 transfer 方法上(该方法是数据扩容时将数据从旧容器转移到新容器)。 仔细分析了一下里面的代码,基本得出了原因,证明了我之前的推测。
假设扩容时的一个场景如下(右边的容器是一个长度 2 倍于当前容器的数组) 单线程情况。
我们分析数据转移的过程,主要是链表的转移。
执行过一次后的状态:
最终的结果:
两个线程并发情况下,扩容时可能会创建出 2 个新数组容器
顺利的话,最终转移完可能是这样的结果
但并发情况下,出现死循环的可能场景是什么呢? 还要详细的分析一下代码,下面的代码中重点在 do/while 循环结构中(完成链 表的转移)。
// 扩容操作,从一个数组转移到另一个数组
void transfer(Entry[] newTable) {
Entry[] src =
int newCapacity = newTable.
for (int j = 0; j & src. j++) {
Entry&K,V& e = src[j];
if (e != null) {
Entry&K,V& next = e. //假设第一个线程执行到这里
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] =
} while (e != null); // 可能导致死循环
2 个线程并发情况下, 当线程 1 执行到上面第 9 行时,而线程 2 已经完成了一 轮 do/while 操作,那么它的状态如下图:
(上面的数组时线程 1 的,已经完成了链表数据的转移;下面的是线程 2 的,它 即将开始进行对链表数据的转移,此时它记录 E1 和 E2 的首位已经被线程 1 翻 转了)
后续的步骤如下:
1) 插入 E1 节点,E1 节点的 next 指向新容器索引位置上的值(null 或 entry)
2) 插入 E2 节点,E2 的 next 指向当前索引位置上的引用值 E1
3)因为 next 不为 null,链表继续移动,此时 2 节点之间形成了闭环。造成了 死循环。
上面只是一种情况,造成单线程死循环,双核 cpu 的话占用率是 50%,还有导致 100%的情况,应该也都是链表的闭环所致。
最终,这并不是 HashMap 的问题,是使用场景的不当,在并发情况下选择非线程 安全的容器是没有保障的。
相关阅读:,
原创文章,转载请注明: 转载自本文链接地址:
王宏江,阿里巴巴技术专家。
Latest posts by hongjiang ()
Related posts:
(6 votes, average: 4.17 out of 5)
Loading...死循环fo(;;)不断工作造成了CPU使用率100%。&请问怎样才能让CPU的占用不那么高!?????????
回复讨论(解决方案)
Sleep(****);
新开一个线程试试,在线程中来工作&
适当执行Sleep即可。
sleep(10);
死循环了,CPU如何能不高~&中间加上Sleep()延时吧
都是sleep()
1.我在想sleep&会不会影响我需要的实时性??&因为我得目的是实时监控!
2.zhucde&&请教怎么使用线程啊??&&线程的好处是什么?
“实时监控”是监控什么?
sleep自然会影响所在的线程,如果用线程死循环,也得看你是如何监控的。
“实时监控”是监控什么?
我来解读下,每毫秒甚至微妙都在监控
&监控磁盘驱动上的一切
1.&多线程对此问题无贡献,只要你有死循环,CPU总是100%,即使放到子线程也如此。楼上那位在不懂瞎说。不信自己写个子线程看看。
2.&多任务系统无法真正实现实时。人所谓的实时是指人能感知的实时,一般情况下,误差小于1妙的你是感觉不到的,因此100毫秒去检查一次,已经足够快了,根本不需要不停检查
3.&更可怕的是:你这种轮询占领了CPU,实际上对你监控的对象也是有影响的,就好像为了防止自己收细菌感染而不停喝敌敌畏,细菌还没来,你就死了。
3.&如果想“立刻”响应,你不应该通过死循环去轮训,而是要被监控对象完成操作后,尽快通知你,用回调、通知方法才是最合理的。Sleep固然可以消除高CPU问题,但是无法解决立刻响应的问题。因此楼主需要根据自己所涉及的对象,设计回调式、通知式的代码,不同系统式不一样的
比检测精度更快的实时不但是无意义的,也是不可实现的
&监控磁盘驱动上的一切
挂个文件系统过滤驱动
你只能用驱动实现,不能周期性去查询,要是你的监控软件让系统都忙死了,还有啥意义
监控不能用循环来做的
建议Sleep()
让它悬挂一会就好了
可是sys太复杂了。。。
消息或者中断比较好
创建一个内核事件,然后编写响应事件的程序。
请参照,《Windows内核编程》一书。
用不着编写驱动程序。
用死循环加sleep轮询不是Windwos系统下实时监控的思路。
用Timmer定时就可以了,如果要用一直For就民线程优先级降到最低
加个sleep(0)就可以了
13楼是正解。
for循环是根据电脑速度来的,如果某个时段电脑其他方面的事情比较多,你这里的轮询速度就会很慢,相反,你这里的占用100%CPU的循环还会占用系统其他的应用,所以,13楼的2个建议是不错的
第一,用中断代替轮询
第二,修改轮询时间,所谓的实时,你看什么行业的,很多行业的所谓的实时,其实5分钟也叫实时。用Timer多长时间一次轮询一次,这样更稳定。
13楼的话是比较有道理,&对我目前做的录屏项目比较有启发,&但是我想,&线程真的起不到作用吗?
可以控制线程运行的时间来解决占用CPU的问题
可以用事件通知的方式和达到目的嘛,这样死循环,机器再好都受不了.
Sleep或者WaitForSingleObject
13楼的话是比较有道理,&对我目前做的录屏项目比较有启发,&但是我想,&线程真的起不到作用吗?&
可以控制线程运行的时间来解决占用CPU的问题
线程是没法控制时间的。线程的优先级是在系统比较忙的时候同时请求CPU,优先级高的先进入队列,如果系统很闲,或者只有一个线程在跑,优先级是没有用的~
线程的所谓的运行时间,是在操作系统正常运行中各个线程相互抢占CPU后按照比例分配后,各个线程用了多少时间。
while(WatiForSingleObject(hThread,0)&==&WAIT_OBJECT_0)
用select函数可以创建相当精确的时钟,SELECT不止操作SOCKET,同样,文件句柄也可以操作。可以制作时钟.13楼讲的很准确.
控制了时间就达不到你“实时”监控目的了
只有让被监控对象自己通知你,才能做到实时且不占有高CPU
线程对真的占有很多CPU的操作是达不到提高性能的目的的
13楼的话是比较有道理,&对我目前做的录屏项目比较有启发,&但是我想,&线程真的起不到作用吗?&&
可以控制线程运行的时间来解决占用CPU的问题&
线程是没法控制时间的。线程的优先级是在系统比较忙的时候同时请求CPU,优先级高的先进入队列,如果系统很闲,或者只有一个线程在跑,优先级是没有用的~&
线程的所谓的运行时间,是在操作系统正常运行中各个线程相互抢占CPU后按照比例分配后,各个线程用了多少时间。查看: 89|回复: 3
用OnTime方法延迟执行的副作用,一会儿CPU就占用100%了!附件
阅读权限20
在线时间 小时
用OnTime方法延迟执行的副作用,一会儿CPU就占用100%了!附件
一个简单的程序,在a列从A1开始,每隔3秒写入一个数字,由循环计算得出。
Private Sub CommandButton1_Click()
'在a列每隔3秒写入一个数字,由循环计算得出
Dim i, j As Integer
For i = 1 To 10
blnStop = True
Application.OnTime Now + TimeValue(&00:00:3&), &myREDO&& &'&===设定暂停5秒
While blnStop& &'&==前面设了blnSTop为真
DoEvents& & '&==5秒内一直不做什么事,执行Doevents函数(就是系统空循环)
Wend
j = i + 100
Cells(i, 1) = j
End Sub复制代码
下面这个在模块里,被上面的调用:
Sub myREDO()
blnStop = False
End Sub复制代码循环10次还可以,你把循环次数改为100试试,很快就CPU就占用100%了!
DoEvents不是空循环么,交还了系统控制权么,这是怎么回事,怎样避免呢?
(9.37 KB, 下载次数: 3)
18:27 上传
点击文件名下载附件
阅读权限20
在线时间 小时
发现用这个CPU不占用,正常!
但要放在模块里:
Private Declare Sub Sleep Lib &kernel32& (ByVal dwMilliseconds As Long)
Sub yanchi()
Dim i, j As Integer
For i = 1 To 20
j = i + 100
Cells(i, 1) = j
Sleep 2000&&'延时2秒
MsgBox &ok!&
End Sub复制代码
但有个问题在VBA窗口F5运行后,切换不到表格窗口,跟死机一样!!直到运行完毕。
这个怎么办?
阅读权限90
在线时间 小时
一个漂亮自定义的进度条,在状态栏显示,怎样和这个VBA配合呢?
(出处: ExcelHome技术论坛)
阅读权限20
在线时间 小时
确实问题解决了!
不过我不明白原因,是不是我把DoEvents 放在了for循环之间的缘故呢?
还是根本不需要DoEvents 呢?
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师Java项目服务器cpu占用100%解决办法 - 推酷
Java项目服务器cpu占用100%解决办法
项目上线后运行一段时间,突然发现cpu 8个逻辑核心都占用100%,心情很紧张,然后就在网上找了一些解决方法,具体如下:
1.查找哪些进程在耗cpu&
进入服务器,top 命令看一下,发现进程6633占用了800%&
[root@3server ~]# top
2.把进程的栈dump到文件里,以便后面的分析
[root@3server ~]# jstack 6633 & cpu1128.log
3.看看这个进程里面哪些线程在占用cpu&
[root@3server ~]# top -p 6633 -H
一大片占用cpu很高的线程,选一个最高的吧,PID=5159
4.接着要看刚才dump出来的cpu日志了,里面会有6633这个进程下面每个线程的栈信息,但是是十六进制显示的,所以先把5159转换成16进制&
[root@3server ~]# printf %0x 5159
[root@3server ~]# 1427
5.在cpu日志里找PID=1427的线程&
[root@3server ~]# vi cpu1128.log
6.分析原因
看日志,很明显是org.hibernate.exception.ExceptionUtils.getCauseUsingWellKnowTypes(...)这里“卡住”了。这个线程是&RUNABLE&状态的,为什么会&卡住&呢?不用说了,一定是死循环。后来花了很多时间在debug状态下把这个问题重现了(Hibernate 3.3.1.GA版本,通过hessian调用远程服务器报SQLGrammarException异常,就会出现这个问题)。跟踪到hibernate源码里发现了问题:
public static int getThrowableCount(Throwable throwable) {
int count = 0;
while ( throwable != null ) {
throwable = ExceptionUtils.getCause( throwable );
这个方法里,throwable和它的cause引用的同一个SQLGrammarException对象,导致在while这里产生了死循环。这肯定是hibernate的bug了。于是把hibernate升级到3.3.2.GA(原来是3.3.1.GA,不敢升太多)问题解决。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致为何 在循环中加入了DoEvents,cpu依然占用100% - VB Dotnet当前位置:& &&&为何 在循环中加入了DoEvents,cpu依然占用100%为何 在循环中加入了DoEvents,cpu依然占用100%&&网友分享于:&&浏览:9次为什么 在循环中加入了DoEvents,cpu依然占用100%环境vs2012,&.net&Farmework&4.0
新建一个工程,窗体代码如下
Public&Class&Form1
&&&&&&&&Private&Sub&Button1_Click(sender&As&Object,&e&As&EventArgs)&Handles&Button1.Click
&&&&&&&&&&&&&&&&Do
&&&&&&&&&&&&&&&&&&&&&&&&Application.DoEvents()
&&&&&&&&&&&&&&&&Loop
&&&&&&&&End&Sub
为什么&在循环中加入了DoEvents,cpu依然占用100%
如果我这个循环是为了检测一个值是否达到条件,达到条件则继续之后的代码.没达到条件则一直卡在这个循环中,应该如何写呢?
我当前的代码是这样的
Public&Class&Form1
&&&&&&&&Private&Sub&Button1_Click(sender&As&Object,&e&As&EventArgs)&Handles&Button1.Click
&&&&&&&&&&&&&&&&Do
&&&&&&&&&&&&&&&&&&&&&&&&if&(一个判断条件的表达式)&then&exit&do
&&&&&&&&&&&&&&&&&&&&&&&&Application.DoEvents()
&&&&&&&&&&&&&&&&Loop
&&&&&&&&&&&&&&&&'这里是之后的代码
&&&&&&&&End&Sub
------解决方案--------------------DoEvents应该是循环的间隙,处理下消息。所以CPU占有率还是很高。------解决方案--------------------Thread.Sleep(100)------解决方案--------------------引用:试了一下&&&看来这样用才行
Application.DoEvents()
Thread.Sleep(1)
如果只用Application.DoEvents()无法降低CPU使用率
如果只用Thread.Sleep()界面会假死
这种费力气的事情,请新开一个线程去处理,并且在线程里适当Sleep,这样不会影响UI响应,数据处理完毕时,通过Dispatcher传回UI线程来进行显示。------解决方案--------------------引用:Quote: 引用:
其实这里我就是在等待一个BackgroundWorker对象的线程结束
执行方法以前先将界面enable=false
backgroundWorker1的RunWorkerCompleted,完成后&界面&enable=true
等待直到另一个线程结束后再继续后续动作,可使用线程中的WaitOne()方法。VS帮助当中有相关示例如下:
Public&Class&WaitOne
&&&&Shared&autoEvent&As&New&AutoResetEvent(False)
&&&&&MTAThread()&&_
&&&&Shared&Sub&Main()
&&&&&&&&Console.WriteLine("Main&starting.")
&&&&&&&&ThreadPool.QueueUserWorkItem(AddressOf&WorkMethod,&autoEvent)
&&&&&&&&'&Wait&for&work&method&to&signal.
&&&&&&&&autoEvent.WaitOne()
&&&&&&&&Console.WriteLine("Work&method&signaled.")
&&&&&&&&Console.WriteLine("Main&ending.")
&&&&End&Sub
&&&&Shared&Sub&WorkMethod(ByVal&stateInfo&As&Object)
&&&&&&&&Console.WriteLine("Work&starting.")
&&&&&&&&'&Simulate&time&spent&working.
&&&&&&&&Thread.Sleep(New&Random().Next(100,&2000))
&&&&&&&&'&Signal&that&work&is&finished.
&&&&&&&&Console.WriteLine("Work&ending.")
&&&&&&&&CType(stateInfo,&AutoResetEvent).Set()
&&&&End&Sub
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有}

我要回帖

更多关于 win10 cpu占用率高 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信