当前位置:编程学习 > JAVA >>

多线程问题:notify()后线程不是每次都会执行

一个队列,两个线程,一个线程负责往队列里add,另一个从队列removeFirst() 
队列空时就wait(),add一个后就notify(),队列size超过100就丢弃add的对象 
大多情况下执行没问题,但是总有一段时间只执行add,不执行removeFirst(),就算每次add后都执行notify()也不行 
把队列size给添加到100,造成数据丢弃 
请大家帮忙分析下为什么notify后不执行removeFirst(),大致的代码如下 
public   void   SendMsg(byte[]   msg)   { 
byte[]   newmsg; 
newmsg   =   msg.clone(); 
synchronized   (m_out_q)   { 
//   不能过多。注意,过多时,不是等待,而是丢弃 
if   (m_out_q.size()   > =   m_maxsize) 
return; 
m_out_q.addLast(newmsg); 
if   (m_out_q.size()   > =   1)   { 
m_out_q.notify(); 





public   void   run()   { 
byte[]   thismsg   =   null; 
while   (true)   { 
synchronized   (m_out_q)   { 
while   (m_out_q.isEmpty())   { 
try   { 
m_out_q.wait(); 
}   catch   (InterruptedException   e)   { 
e.printStackTrace(); 


thismsg   =   m_out_q.removeFirst(); 
}   //   end   of   synchronized 

UDPService.sendMessage(thismsg); 


--------------------编程问答-------------------- 总有一段时间只执行add,不执行removeFirst(),这就对了。
两线程并不是真正意义上的同时运行,两线程以乱序在执行,多线程切换时不能保证也无法预知哪一线程何时获得CPU等资源而执行。此所谓风水轮流转。
--------------------编程问答--------------------
引用 1 楼 lfp001 的回复:
总有一段时间只执行add,不执行removeFirst(),这就对了。
两线程并不是真正意义上的同时运行,两线程以乱序在执行,多线程切换时不能保证也无法预知哪一线程何时获得CPU等资源而执行。此所谓风水轮流转。
+1 --------------------编程问答-------------------- 你上面的code

if (m_out_q.size() > = m_maxsize)  
return;

改成:

if (m_out_q.size() > = m_maxsize){
m_out_q.notify();
return;
}  

测试下. --------------------编程问答-------------------- 总有一段时间只执行add,不执行removeFirst(),
还有一原因,LZ对m_out_q的操作不是线程安全的。没对m_out_q.removeFirst()同步。

public void run() {
byte[] thismsg = null;
while (true) {
synchronized (m_out_q) {
while (m_out_q.isEmpty()) {
try {
m_out_q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
thismsg = m_out_q.removeFirst(); // 对m_out_q同步
}
} // end of synchronized

UDPService.sendMessage(thismsg);
}
}
--------------------编程问答-------------------- 咱们先来看SendMsg(byte[] msg) 方法。LZ只用了m_out_q.notify();  而没有m_out_q.wait()方法。这会导致一个状况就是这个线程根本不会停下来。一直运行。一直运行就会长时间的站有锁。而run() 方法里面却m_out_q.wait();导致好不容易拿来的锁一下子就释放了,线程又进入休眠状态了。直到没准什么时候会被唤醒。所以会导致LZ说的这种现象。notify和wait应该都是配对使用的。 --------------------编程问答--------------------
引用 3 楼 lxbccsu 的回复:
你上面的code

Java code


if (m_out_q.size() > = m_maxsize)  
return;


改成:

Java code


if (m_out_q.size() > = m_maxsize){
m_out_q.notify();
return;
}  


测试下.


+1
当队列达到最大的时候,没有通知另一个删除线程,这样删除线程就一直处于等待
而追加线程每次if (m_out_q.size() > = m_maxsize){在这里都直接返回,删除线程就一直不会被唤醒

--------------------编程问答--------------------
引用 5 楼 jc8futao 的回复:
咱们先来看SendMsg(byte[] msg) 方法。LZ只用了m_out_q.notify();  而没有m_out_q.wait()方法。这会导致一个状况就是这个线程根本不会停下来。一直运行。一直运行就会长时间的站有锁。而run() 方法里面却m_out_q.wait();导致好不容易拿来的锁一下子就释放了,线程又进入休眠状态了。直到没准什么时候会被唤醒。所以会导致LZ说的这种现象。not……


+1
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,