简体   繁体   English

java.lang.IllegalMonitorStateException:在等待()之前对象没有被线程锁定?

[英]java.lang.IllegalMonitorStateException: object not locked by thread before wait()?

I am using ProgressDialog.我正在使用 ProgressDialog。 I need to stop the thread when a user closes the ProgressDialog.当用户关闭 ProgressDialog 时,我需要停止线程。 Unfortunately, it is giving an exception.不幸的是,它给出了一个例外。

In inner class:在内部类中:

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

Oncreate:创建:

 updateThread=new UpdateThread();

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

Ondismissal:解雇:

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

This is wrong:这是错误的:

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

The problem is, what's going to wake this thread up?问题是,什么会唤醒这个线程? That is to say, how do you guarantee that the other thread won't call foo.notify() before the first thread calls foo.wait() ?也就是说,如何保证在第一个线程调用 foo.wait foo.notify()之前,另一个线程不会调用foo.wait() That's important because the foo object will not remember that it was notified if the notify call happens first.这很重要,因为如果 notify 调用首先发生, foo 对象将不会记住它已被通知。 If there's only one notify(), and if it happens before the wait(), then the wait() will never return.如果只有一个 notify(),并且它发生在 wait() 之前,那么 wait() 将永远不会返回。

Here's how wait and notify were meant to be used:下面是 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);
}

The most important things to to note in this example are that there is an explicit test for the condition (ie, q.peek() != null), and that nobody changes the condition without locking the lock.在这个例子中要注意的最重要的事情是对条件有一个明确的测试(即 q.peek() != null),并且没有人在不锁定锁的情况下更改条件。

If the consumer is called first, then it will find the queue empty, and it will wait.如果消费者先被调用,那么它会发现队列是空的,它会等待。 There is no moment when the producer can slip in, add a Product to the queue, and then notify the lock until the consumer is ready to receive that notification.生产者没有时间可以溜进来,将产品添加到队列中,然后通知锁,直到消费者准备好接收该通知。

On the other hand, if the producer is called first, then the consumer is guaranteed not to call wait().另一方面,如果先调用生产者,则保证消费者不会调用wait()。

The loop in the consumer is important for two reasons: One is that, if there is more than one consumer thread, then it is possible for one consumer to receive a notification, but then another consumer sneaks in and steals the Product from the queue.消费者中的循环之所以重要,有两个原因:一是,如果有多个消费者线程,那么一个消费者可能会收到通知,但随后另一个消费者会潜入并从队列中窃取产品。 The only reasonable thing for the fist consumer to do in that case is wait again for the next Product.在这种情况下,第一个消费者唯一合理的做法是再次等待下一个产品。 The other reason that the loop is important is that the Javadoc says Object.wait() is allowed to return even when the object has not been notified.循环很重要的另一个原因是 Javadoc 说 Object.wait() 被允许返回,即使对象没有被通知。 That is called a "spurious wakeup", and the correct way to handle it is to go back and wait again.这被称为“虚假唤醒”,处理它的正确方法是返回并再次等待。

Also note: The lock is private and the queue is private .另请注意:锁是private的,队列是private的。 That guarantees that no other compilation unit is going to interfere with the synchronization in this compilation unit.这保证了没有其他编译单元会干扰此编译单元中的同步。

And note: The lock is a different object from the queue itself.请注意:锁是与队列本身不同的对象。 That guarantees that synchronization in this compilation unit will not interfere with whatever synchronization that the Queue implementation does (if any).这保证了此编译单元中的同步不会干扰 Queue 实现所做的任何同步(如果有的话)。


NOTE: My example re-invents a wheel to prove a point.注意:我的示例重新发明了一个轮子来证明一个观点。 In real code, you would use the put() and take() methods of an ArrayBlockingQueue which would take care of all of the waiting and notifying for you.在实际代码中,您将使用 ArrayBlockingQueue 的 put() 和 take() 方法,它们会为您处理所有等待和通知。

You can only wait on an object if you already hold the lock on it, you could try:如果你已经持有一个对象,你只能等待一个对象,你可以尝试:

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

... but I'm not really sure what you're trying to achieve with the locks. ...但我不太确定你想用锁实现什么。

It really looks like you're trying to use synchronized and wait where you shouldn't be.看起来您确实在尝试使用synchronizedwait您不应该在的地方。

If you really want to wait for the thread to finish, you should be doing something like this如果你真的想等待线程完成,你应该做这样的事情

In your UpdateThread :在您的UpdateThread

class UpdateThread extends Thread{
    public AtomicBoolean stopped = new AtomicBoolean(false);
    public  void run() {
        while (!stopped.get()){
    .....

In your creation:在您的创作中:

updateThread = new UpdateThread();
progressDialog = new ProgressDialog(GroupListActivity.this);
updateThread.start();    // no synchronization necessary

In your on dismiss:在您的解雇中:

progressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public  void onDismiss(DialogInterface dialog) {
            try {
                updateThread.stopped.set(true);
                updateThread.join(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG,"Thread is stopped");
        }
    });

Note, I added an exit condition to your thread so it will actually stop (as is, your thread will keep going).请注意,我向您的线程添加了一个退出条件,因此它实际上会停止(因为您的线程将继续运行)。 You'd probably want to make the exit condition private and add a setter for cleanliness.您可能希望将退出条件设为私有并添加一个用于清洁的设置器。 Also, I'm using join to properly wait for your thread to complete.另外,我正在使用join正确等待您的线程完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android:java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定 - Android: java.lang.IllegalMonitorStateException: object not locked by thread before wait() java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定 - java.lang.IllegalMonitorStateException: object not locked by thread before wait() Android java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定 - Android java.lang.IllegalMonitorStateException: object not locked by thread before wait() 线程“main”java.lang.IllegalMonitorStateException中的异常 - Exception in thread “main” java.lang.IllegalMonitorStateException 线程“ AWT-EventQueue-0”中的异常java.lang.Object.notify上的java.lang.IllegalMonitorStateException(本机方法) - Exception in thread “AWT-EventQueue-0” java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) IllegalMonitorStateException: 对象在 wait() 之前未被线程锁定,使用同步静态方法 - IllegalMonitorStateException: object not locked by thread before wait(), using synchronized static method 从同步块中调用wait时发生java.lang.IllegalMonitorStateException - java.lang.IllegalMonitorStateException whilst calling wait from synchronized block 超时时发生java.lang.IllegalMonitorStateException - java.lang.IllegalMonitorStateException on timeout 线程通信:如何发出信号,表明已单击某个键? java.lang.IllegalMonitorStateException - Thread communication: How to signal that a key was clicked? java.lang.IllegalMonitorStateException java.lang.IllegalMonitorStateException: 当前线程不是锁的所有者 - java.lang.IllegalMonitorStateException: Current thread is not owner of the lock
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM