【问题标题】:IllegalMonitorStateException: object not locked by thread before notify()IllegalMonitorStateException:对象在 notify() 之前未被线程锁定
【发布时间】:2014-08-12 14:55:23
【问题描述】:

是的,我以前看过类似主题的问题,但它们似乎对我没有帮助。如有重复,请指出问题,谢谢

我这里有两个问题,第一个是标题问题:

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

据我了解,如果它是错误的,请纠正我,wait() 的作用是暂停所有正在运行的代码,直到发生事件,例如单击按钮导致 notify() 被调用。

第二个问题是在我点击按钮之前,Toast 就出现了。我假设当我调用 wait() 时,所有代码都会等待,直到我单击按钮,其中 notify() 将被调用并且代码将继续。但实际上,Toast 似乎忽略了 wait() 并继续运行。

如果有任何问题,请尽管问,谢谢。

编辑:logcat 消息显示崩溃发生在:

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

【问题讨论】:

  • "第二个问题是甚至在我单击按钮之前,Toast 就出现了。我假设当我调用 wait() 时,所有代码都会等到我单击按钮,其中 notify() 将是“这是因为您在代码中有 3 个线程,一个 UI 线程继续执行和您创建的 2 个不同线程,UI 线程从线程的创建跳转并继续,因此它面向您的 toast !!!
  • “wait() 的作用是停止所有正在运行的代码” 不确定您所说的 all 正在运行的代码是什么意思。 foo.wait() 所做的是,它释放 foo 的监视器,等待通知,重新获取 foo 的监视器,然后返回。它不会“停止”任何其他线程。

标签: java android multithreading


【解决方案1】:

这里

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

您锁定了findViewByIdsetOnClickListener 的调用,但没有锁定onClick 方法,因此调用notify 的时间在任何同步块之外。

您应该将锁移动到 onClick 方法中,这是要阻止的代码块

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

记住 this 在内部类中是不同的

无论如何不建议使用wait/notify,考虑使用JDK中的其他多线程类和集合之一。


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

在这里你同步 Runnable 而不是主类。

【讨论】:

  • 我已经修改了代码,但仍然出现错误。我刚刚将“this”改成了“SecondClass.this”(代码所在的类),但错误信息仍然存在。
  • 是异常,反正是因为thread2启动时thread1还没有启动
  • 那么 thread.sleep(500) 会解决这个问题吗?编辑:哎呀,这没有意义
  • 不,因为您使用的不是单线程程序。可能会发生这样的情况,即使在 500 毫秒之后,Android 还没有启动线程,因为它现在不能或类似的事情。
  • 无论如何要解决这个问题,还是 android 就是这样?
猜你喜欢
  • 2018-11-02
  • 2014-10-07
  • 1970-01-01
  • 2014-08-02
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 2014-12-22
相关资源
最近更新 更多