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

patch 2011-11-16 05:33:31
一个队列,两个线程,一个线程负责往队列里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);
}
}
...全文
237 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
lxbccsu 2011-11-17
  • 打赏
  • 举报
回复
你上面的code

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

改成:

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

测试下.
Tirion_Fordring 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jc8futao 的回复:]

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

+1
qybao 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 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;
}


测试下.
[/Quote]

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

jc8futao 2011-11-17
  • 打赏
  • 举报
回复
咱们先来看SendMsg(byte[] msg) 方法。LZ只用了m_out_q.notify(); 而没有m_out_q.wait()方法。这会导致一个状况就是这个线程根本不会停下来。一直运行。一直运行就会长时间的站有锁。而run() 方法里面却m_out_q.wait();导致好不容易拿来的锁一下子就释放了,线程又进入休眠状态了。直到没准什么时候会被唤醒。所以会导致LZ说的这种现象。notify和wait应该都是配对使用的。
lfp001 2011-11-17
  • 打赏
  • 举报
回复
总有一段时间只执行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);
}
}
afunx 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lfp001 的回复:]
总有一段时间只执行add,不执行removeFirst(),这就对了。
两线程并不是真正意义上的同时运行,两线程以乱序在执行,多线程切换时不能保证也无法预知哪一线程何时获得CPU等资源而执行。此所谓风水轮流转。
[/Quote]+1
lfp001 2011-11-16
  • 打赏
  • 举报
回复
总有一段时间只执行add,不执行removeFirst(),这就对了。
两线程并不是真正意义上的同时运行,两线程以乱序在执行,多线程切换时不能保证也无法预知哪一线程何时获得CPU等资源而执行。此所谓风水轮流转。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧