线程wait, notify使用错误java.lang.IllegalMonitorStateException

ameyume
博客专家认证
2010-11-14 05:35:38
我在播放音乐时,启动了一个线程,每个200ms执行一次刷新播放进度的操作。
当我点击播放下一首时,使用wait先暂停此线程,当播放开始后,在notify唤醒此线程继续执行
但是点击下一首时,中断,报以下错误:
java.lang.IllegalMonitorStateException:object not locked by thread before notify()
处理代码如下:
1.下一首
if (v == mNext) { // 下一首
stopProgressUpdate();
playMusic(MusicService.NEXT_ACTION);
// 开始播放,按钮显示为暂停
mPlay.setImageResource(R.drawable.pause);
playPauseStatus = 1;
startProgressUpdate();
}


2.notify方法处理
public void startProgressUpdate() {
// 开辟Thread 用于定期刷新SeekBar

if (dThread == null) {
// 创建线程
dThread = new DelayThread(200);
dThread.start();
} else {
// 恢复线程
synchronized(this) {
dThread.notify();
}
}
mbSeekBarUpdateFlg = true;
}

3.线程的wait方法
	// 延迟处理
public class DelayThread extends Thread {
private int milliseconds; // 延迟的时间

public DelayThread(int i) {
milliseconds = i;
}

public void run() {
while(!mbSeekBarStopFlg) {
if (mbSeekBarUpdateFlg) {
try {
sleep(milliseconds);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// 延迟指定的时间后,执行更新播放时间
mHandle.sendEmptyMessage(0);
} else {
synchronized(this){
try {
dThread.wait(); // 暂停线程
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}

4.停止刷新只是设置了标志
	public void stopProgressUpdate() {
// 停止Thread,停止刷新SeekBar
mbSeekBarUpdateFlg = false;
}
...全文
26406 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
wd_ybyq 2011-06-11
  • 打赏
  • 举报
回复
synchronized(this)
{
try {
dThread.wait(); // 暂停线程
}catch(InterruptedException e) {
e.printStackTrace();
}
}
synchronized(this),会获得this的对象锁,dThread.wait()会让该调用线程wait在dThread对象的等待池中,然后该线程会释放dThread锁,由于线程没有dThread对象锁,所以会报IllegalMonitorStateException。同样的道理适合notify(),notifyAll().
所以可以这样写:
synchronized(dThread)
{
try {
dThread.wait(); // 暂停线程
}catch(InterruptedException e) {
e.printStackTrace();
}
}
synchronized(dThread)
{
dThread.notify(); // 恢复线程
}


wait的目的就在于暴露出对象锁,让其他线程可以通过对象的notify叫醒等待在该对象的等该池里的线程。同样notify也会释放对象锁,在调用之前必须获得对象的锁,不然也会报异常。
hackkuang001 2010-11-14
  • 打赏
  • 举报
回复
# 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。
hackkuang001 2010-11-14
  • 打赏
  • 举报
回复
wait:等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则后收到一个 IllegalMonitorStateException,这个是运行时异常.调用这个方法后,就放弃了这个同步锁了.如果不带参数的wait方法就只 有等别人唤醒了,如果带一个参数的
化就设置等待最长时间,过了这个时间即使没有人唤醒这个线程也不再等待了.
notify:唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),但是notifyAll可以唤醒所有等待的线程,注意唤醒的时在notify之前wait的线程,之后的没有效果.
ameyume 2010-11-14
  • 打赏
  • 举报
回复
没用wait,notify之前是点击下一首时,我都是重新new一个DelayThread(200);
但这样连续点击下一首时,就死机了。

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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