java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定? [英] java.lang.IllegalMonitorStateException: object not locked by thread before wait()?

查看:24
本文介绍了java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用进度对话框.当用户关闭进度对话框时,我需要停止线程.不幸的是,它给出了异常,请帮助我..

I am using progress dialog.i need to stop the thread when user close the progressdialog .unfortunately it giving exception pls help me..

内部类

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

推荐答案

这是错误的:

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

问题是,什么会唤醒这个线程?也就是说,你如何保证另一个线程不会调用foo.notify() 在第一个线程调用>foo.wait()?这很重要,因为如果首先发生通知调用,则 foo 对象将不会记住它已收到通知.如果只有一个notify(),并且它发生在wait()之前,那么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()? That's important because the foo object will not remember that it was notified if the notify call happens first. If there's only one notify(), and if it happens before the wait(), then the wait() will never return.

等待和通知的用法如下:

Here's how wait and notify were meant to be used:

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),并且没有人在不锁定锁的情况下改变条件.

The most important things to to note in this example are that there is an explicit test for the condition (i.e., q.peek() != null), and that nobody changes the condition without locking the lock.

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

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.

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

On the other hand, if the producer is called first, then the consumer is guaranteed not to call wait().

消费者中的循环很重要,原因有二:一是,如果有多个消费者线程,则有可能一个消费者收到通知,但随后另一个消费者潜入并从队列.在这种情况下,第一个消费者唯一合理的做法就是再次等待下一个产品.循环很重要的另一个原因是 Javadoc 说 Object.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. That is called a "spurious wakeup", and the correct way to handle it is to go back and wait again.

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

Also note: The lock is private and the queue is private. That guarantees that no other compilation unit is going to interfere with the synchronization in this compilation unit.

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

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).

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

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.

这篇关于java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆