user3746541
user3746541

Reputation:

IllegalMonitorStateException: object not locked by thread before notify()

Yes, I have seen previous questions on similar topics, but they don't seem to help me. If there is a duplicate, please point me to the question, thanks

I have two problems here, the first one is the title problem:

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
//Starts up method1 & method2 in a try-catch
    try{
        method1();
        method2();
        new CountDownLatch(1);
        CountDownLatch.await();
    }catch(InterruptedException e){
        // TODO Auto-generated catch
        // block
        e.printStackTrace();
    }
//This Toast should only run after notify() is called
    Toast.makeText(firstClass.this, "This is toasty", Toast.LENGTH_SHORT).show();
}


//Start of method 1, which is currently useless
public void method1() throws InterruptedException{
//Creates new thread
    Thread thread = new Thread(new Runnable(){
        @Override
        public void run(){
            try{
                synchronized(SecondClass.this){
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }

    });
    thread.start();
}

public void method2(){
    Thread thread2 = new Thread(new Runnable(){
        @Override
        public void run(){

//Sets a button, when the button is clicked, then the code is continued
                final Button bNext = (Button) findViewById(R.id.bIsoAbunSave);
                bNext.setOnClickListener(new OnClickListener(){
                    @Override
                    public void onClick(View arg0){
                        synchronized(SecondClass.this){
                        CountDownLatch.countDown();
                       }
                    }
                });
            }


    });
    thread2.start();
}

From what I understand, please correct me if its false, what wait() does is it halts all running code until an event, such as a click of a button causes notify() to be called.

The second problem is even before I click the button, the Toast shows up. I assumed when I called wait(), all code would wait until I clicked the button, where notify() would be called and the code would be continued. But what happens instead is that the Toast is seemingly ignoring the wait() and running anyways.

If there are any questions, please ask away, thanks.

EDIT: The logcat message shows that the crash happens at:

synchronized(SecondClass.this){notify();}

Upvotes: 0

Views: 13368

Answers (1)

Marco Acierno
Marco Acierno

Reputation: 14847

Here

synchronized(this){
//Sets a button, when the button is clicked, then the code is continued
            final Button bNext = (Button) findViewById(R.id.bIsoAbunSave);
            bNext.setOnClickListener(new OnClickListener(){
                @Override
                public void onClick(View arg0){
                    notify();
                }
            });
}

You lock the invocation of findViewById and the setOnClickListener but not the onClick method, so when is invoked notify is outside any syncronized block.

You should move the lock inside the onClick method which is the code-block to block

//Sets a button, when the button is clicked, then the code is continued
            final Button bNext = (Button) findViewById(R.id.bIsoAbunSave);
            bNext.setOnClickListener(new OnClickListener(){
                @Override
                public void onClick(View arg0){
                    synchronized(TopClass.this){ notify(); }
                }
            });

(remember this is different in an inner-class)

Anyway the use of wait/notify is not recommended, consider using one of the other multithread classes and collections in the JDK.


synchronized(this){
   //These statements *should* make the code wait until I click the button
   wait();
}

Here you syncronizate the Runnable not the main class.

Upvotes: 1

Related Questions