IllegalMonitorStateException: объект не заблокирован потоком перед wait () - PullRequest
0 голосов
/ 23 мая 2018

Я знаю, что есть много подобных вопросов, но никто не помог мне. Я получаю 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 голосов
/ 24 мая 2018

"Цель состоит в том, чтобы запустить поток, поставить его на паузу и после возобновления"

Приостановка и возобновление потоков в Java - плохая практика, поскольку приводит к тонким и трудным для отладки ошибкам.

Единственный надежный способ остановить / возобновить какой-либо вычислительный процесс - это разделить этот процесс на части, обработать эти части в цикле и перед началом обработки следующей части проверить, разрешена ли обработка.

Как эволюцияПри таком подходе каждая часть формируется как Runnable и представляется однопоточным Executor.Вместо остановки и возобновления Executor поток (-ы) производителя просто останавливают и возобновляют отправку частичных задач исполнителю.

Если (некоторые) части могут обрабатываться параллельно, тогда может использоваться многопоточный исполнитель, но это требует координации между подачей конкретных заданий.

0 голосов
/ 24 мая 2018

Цель - запустить поток, поставить его на паузу и после возобновления

Вот фрагмент кода, который я использую для приостановки и возобновления потока.

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
}
0 голосов
/ 23 мая 2018

"объект не заблокирован потоком перед wait ()"

Подумайте, какой объект подразумевается в этом сообщении?Тот самый объект, для которого применяется wait():

recordingThread.wait();

, то есть recordingThread.

synchronized void stopRecordingAndRecognition не имеет значения, поскольку он блокирует this объект, а не recordingThread.

Итак, есть 2 решения:

  • принудительно синхронизировать методы на recordingThread
  • встроить синхронизированные методы в класс recordingThread
...