【问题标题】:IllegalMonitorStateException: object not locked by thread before wait()IllegalMonitorStateException:对象在 wait() 之前未被线程锁定
【发布时间】:2018-11-02 14:35:54
【问题描述】:

我知道有很多类似的问题,但没有人帮助我。当我尝试暂停线程时,我收到了IllegalMonitorStateException: object not locked by thread before wait()

这是我的初始化方法:

// called only once in constructor; the variables are global ( private Thread ... )
    public void init() {

        recordingThread = new Thread(new Runnable() {
            @Override
            public void run() {
                isNewRecordingThread= false;
                record();
            }
        });

        recognitionThread = new Thread(new Runnable() {
            @Override
            public void run() {
                isNewRecognition= false;
                recognize();
            }
        });
...
}

startRecording方法:

private synchronized void startRecording(Thread recordingThread) {
    if(isNewRecordingThread){
        recordingThread.start();
        return;
    }
    recordingThread.notify();
}

开始识别方法:

private synchronized void startRecognition(Thread recognitionThread) {
    shouldContinueRecognition = true;
    if(isNewRecognition){
        recognitionThread.start();
        return;
    }
    recognitionThread.notify();
}

以及我实际得到错误的停止方法:

private synchronized void stopRecordingAndRecognition(Thread recordingThread, Thread recognitionThread) {
    try{
        if (recordingThread != null && recordingThread.isAlive()) {
            recordingThread.wait();
        }
        if (recognitionThread != null && recognitionThread.isAlive()) {
            recognitionThread.wait();
        }
    } catch (InterruptedException e){
        Log.d("TESTING","InterruptedException e= "+e);
    }
}

【问题讨论】:

  • 在没有循环的情况下调用wait()/await() 不是一个好主意,因为您可能会错过信号或出现虚假唤醒!
  • 任何想法如何使它更好?
  • @abrutsze 如果我们不知道您想要实现什么,我们如何才能做得更好。
  • 目标是启动线程,暂停它并在恢复之后
  • @abrutsze 我添加了一个用于暂停/恢复线程的代码 sn-p。

标签: java android multithreading wait java-threads


【解决方案1】:

目标是启动线程,暂停它并在恢复之后

这是我用来暂停和恢复线程的代码 sn-p。

public class ThreadStatus { 
    private boolean paused;
    private final String threadName;
    private final ReentrantLock lock;
    private final Condition condition;

    public ThreadStatus (String name) {
        threadName = name;
        lock = new ReentrantLock();
        condition = lock.newCondition();
        paused = false;
    }

    // check for the thread to be paused
    public void checkForPause() {
        lock.lock();
        try {
            while (paused) {                
                condition.await();
            }
        } catch (InterruptedException ie) {
            // interrupted
        } finally {
            lock.unlock();
        }
    }

    // Pause the thread
    public void pause() {
        lock.lock();
        try {
            paused = true;
        } finally {
            lock.unlock();
        }
    }

    // Resume the thread
    public void resume() {
        lock.lock();
        try {
            paused = false;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    @Override
    public String toString() {
        return threadName;
    }
}

如果您需要,您可以类似地实现isStopped()isRunning()

final ThreadStatus threadStatus = new ThreadStatus("Thread-A");

在客户端代码中,在相关点调用threadStatus.checkForPause()。例如,如果你在一个循环中有一些重复的处理,你可以这样做 -

while (!threadStatus.isStopped()) {
      threadStatus.checkForPause();   

     // do your processing here
}

【讨论】:

  • 谢谢,会检查的。 :)
【解决方案2】:

“目标是启动线程,暂停它并在恢复后”

在 Java 中暂停和恢复线程是一种不好的做法,因为会导致细微且难以调试的错误。

停止/恢复某些计算过程的唯一可靠方法是将此过程拆分为多个部分,循环处理该部分,并在开始处理下一部分之前检查是否允许处理。

作为这种方法的演变,每个部分都形成为Runnable,并提交给单线程Executor。生产者线程无需停止和恢复Executor,而是简单地停止并恢复将部分任务提交给执行程序。

如果(某些)部分可以并行处理,则可以使用多线程执行器,但需要在提交特定任务之间进行协调。

【讨论】:

  • 谢谢,会检查的。 :)
【解决方案3】:

"在wait()之前对象没有被线程锁定"

想一想,这条消息中的对象是什么?应用wait() 的那个对象:

recordingThread.wait();

recordingThread

synchronized void stopRecordingAndRecognition 无关紧要,因为它锁定了this 对象,而不是recordingThread

所以,有两种解决方案:

  • 强制方法同步recordingThread
  • 将同步方法嵌入到recordingThread的类中

【讨论】:

  • 您能否提供更多关于如何具体实施您的任何解决方案的信息?
  • @abrutsze 看看我的另一个答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 2014-10-07
  • 2017-03-17
  • 2014-12-22
  • 2018-11-30
相关资源
最近更新 更多