3

I know that there are a lot of similar questions, but no one helped me. I am getting IllegalMonitorStateException: object not locked by thread before wait() when I try to pause the thread.

Here is my initialization method:

// 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 method:

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

startRecognition method:

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

And the stopping method where I actually get the error:

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); } } 
5
  • 2
    It's not a good idea to call wait()/await() without loop because you can miss a signal or have a spurious wake-up! Commented May 23, 2018 at 16:23
  • Any ideas how to make it better ? Commented May 23, 2018 at 18:08
  • @abrutsze how can we make it better if we don't know what you want to achieve. Commented May 23, 2018 at 20:28
  • The goal is to start thread, pause it and after resume Commented May 23, 2018 at 20:29
  • @abrutsze I have added a code snippet for pausing/resuming a thread. Commented May 24, 2018 at 13:50

3 Answers 3

1

"object not locked by thread before wait()"

Think, what object is meant in this message? That very object for which wait() is applied:

recordingThread.wait(); 

that is, recordingThread.

synchronized void stopRecordingAndRecognition is irrelevant because it locks this object, and not recordingThread.

So, there are 2 solutions:

  • force methods to synchronize on recordingThread
  • embed synchronized methods into the class of recordingThread
Sign up to request clarification or add additional context in comments.

3 Comments

can you give a bit more information about how exactly to implement any of your solutions, please ?
@abrutsze see my another answer
This should be the accepted answer, because it explains a common mistake. :)
1

"The goal is to start thread, pause it and after resume"

Pausing and resuming threads in Java is a bad practice because leads to subtle and hard to debug errors.

The only reliable way to stop/resume some computational process is to split this process into parts, process that parts in a loop, and before the start of processing the next part, checking if processing is allowed.

As an evolution of this approach, each part is formed as a Runnable and is submitted to a single-threaded Executor. Instead of stop and resume the Executor, producer thread(s) simply stop and resume submitting the partial tasks to the executor.

If (some) parts can be processed in parallel, then multithreaded executor can be used, but it requires coordination between submitting particular tasks.

1 Comment

Thanks, will check it. :)
1

The goal is to start thread, pause it and after resume

Here is a code snippet that I use for suspending and resuming a thread.

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

If you need you could implement isStopped() or isRunning() similarly.

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

In the client code, call threadStatus.checkForPause() at the relevant point. For example, if you have some repeated processings inside a loop, you can do something like -

while (!threadStatus.isStopped()) { threadStatus.checkForPause(); // do your processing here } 

1 Comment

Thanks, will check it. :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.