IllegalMonitorStateException:对象在wait()之前未被线程锁定

时间:2018-05-23 14:36:51

标签: java android multithreading wait java-threads

我知道有很多类似的问题,但没有人帮助我。当我尝试暂停线程时,我收到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();
}

startRecognition方法:

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);
    }
}

3 个答案:

答案 0 :(得分:1)

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

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

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

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

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

答案 1 :(得分:1)

  

目标是启动线程,暂停和恢复后

以下是我用于暂停和恢复线程的代码段。

getPartitionedState()

如果需要,您可以同样实施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()

答案 2 :(得分:0)

"对象在wait()"

之前未被线程锁定

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

recordingThread.wait();

recordingThread

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

所以,有两个解决方案:

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