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

新手上路,请多包涵

我正在使用 ProgressDialog。当用户关闭 ProgressDialog 时,我需要停止线程。不幸的是,它给出了一个例外。

在内部类中:

 class UpdateThread extends Thread{

    public  void run() {
        while (true){
            count=adapter.getCount();

            try {
               mHandler.post(  new Runnable() {
                    public  void run() {
                        Log.i(TAG,count+"count");
                        progressDialog.setMessage(count + "Device  found");
                    }
                });
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

创建时:

  updateThread=new UpdateThread();

 progressDialog= new ProgressDialog(GroupListActivity.this);
 synchronized (this) {
     updateThread.start();
 }

开除:

    progressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public  void onDismiss(DialogInterface dialog) {
            try {
                synchronized (this) {
                    updateThread.wait(300);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG,"Thread is stopped");
        }
    });

原文由 Asthme 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 758
2 个回答

这是错误的:

 synchronized(foo) {
    foo.wait();
}

问题是,什么会唤醒这个线程?也就是说,你如何 保证 另一个线程不会在第一个线程调用 --- foo.notify() 之前 调用 foo.wait() ?这很重要,因为如果 notify 调用先发生,foo 对象将不会记住它已收到通知。如果只有一个 notify(),并且它发生在 wait() 之前,那么 wait() 将永远不会返回。

下面是 wait 和 notify 的用法:

 private Queue<Product> q = ...;
private Object lock = new Object();

void produceSomething(...) {
    Product p = reallyProduceSomething();
    synchronized(lock) {
        q.add(p);
        lock.notify();
    }
}

void consumeSomething(...) {
    Product p = null;
    synchronized(lock) {
        while (q.peek() == null) {
            lock.wait();
        }
        p = q.remove();
    }
    reallyConsume(p);
}

在这个例子中要注意的最重要的事情是对条件有一个显式测试(即 q.peek() != null),并且没有人在不锁定锁的情况下更改条件。

如果消费者先被调用,那么它会发现队列是空的,它会等待。生产者没有时间可以溜进去,将产品添加到队列中,然后通知锁,直到消费者准备好接收该通知。

另一方面,如果先调用生产者,则保证消费者不会调用 wait()。

消费者中的循环很重要,原因有两个:一个是,如果有多个消费者线程,那么一个消费者可能会收到通知,但随后另一个消费者会潜入并从队列中窃取 Product。在这种情况下,第一个消费者唯一合理的做法就是再次等待下一个产品。循环很重要的另一个原因是 Javadoc 说 Object.wait() 允许返回,即使对象没有被通知。这被称为“虚假唤醒”,正确的处理方法是返回并再次等待。

另请注意:锁是 private 队列是 private 。这保证没有其他编译单元会干扰该编译单元中的同步。

并注意:锁是与队列本身不同的对象。这保证了此编译单元中的同步不会干扰 Queue 实现所做的任何同步(如果有)。


注意:我的例子重新发明了一个轮子来证明一个观点。在实际代码中,您将使用 ArrayBlockingQueue 的 put() 和 take() 方法,它们会为您处理所有等待和通知。

原文由 Solomon Slow 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果你已经锁定了一个对象,你只能等待它,你可以尝试:

 synchronized (updateThread) {
    updateThread.wait(300);
}

…但我不太确定你想用锁实现什么。

原文由 BarrySW19 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题