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

2023-09-12 22:53:02 作者:半島煙盒√

我使用进度dialog.i需要停止线程,当用户关闭progressdialog。不幸的是给予例外请帮助我..

在内部类

 类UpdateThread继承Thread {

    公共无效的run(){
        而(真){
            数= adapter.getCount();

            尝试 {
               mHandler.post(新的Runnable(){
                    公共无效的run(){
                        Log.i(TAG,算上+伯爵);
                        progressDialog.setMessage(数+设备发现);
                    }
                });
                视频下载(300);
            }赶上(InterruptedException异常E){
                e.printStackTrace();
            }
        }
    }
}
 

在OnCreate

  updateThread =新UpdateThread();

 progressDialog =新ProgressDialog(GroupListActivity.this);
 同步(本){
     updateThread.start();
 }
 
Java 混淆工具 ProGuard 之初体验

ondismissal

  progressDialog.setOnDismissListener(新DialogInterface.OnDismissListener(){
        @覆盖
        公共无效onDismiss(DialogInterface对话){
            尝试 {
                同步(本){
                    updateThread.wait(300);
                }

            }赶上(InterruptedException异常E){
                e.printStackTrace();
            }
            Log.i(TAG,线程停止);
        }
    });
 

解决方案

这是错误的:

 同步(富){
    foo.wait();
}
 

现在的问题是,这是怎么回事,以唤醒这个线程呢?也就是说,你怎么的保证的另一个线程不会叫 foo.notify()的在的第一个线程调用 foo.wait()?这一点很重要,因为foo的对象不会记得它被通知,如果通知调用首先发生。如果只有一个通知(),如果它等待(前发生的),然后等待()将永远不会返回。

下面是如何等待通知的意思是使用:

 专用队列<产品> Q = ...;
私人对象锁=新的对象();

无效produceSomething(...){
    产品p = reallyProduceSomething();
    同步(锁){
        q.add(对);
        lock.notify();
    }
}

无效consumeSomething(...){
    产品p = NULL;
    同步(锁){
        而(q.peek()== NULL){
            lock.wait();
        }
        p值= q.remove();
    }
    reallyConsume(对);
}
 

要在本实施例中注意是有明确的测试条件(即q.peek()!= NULL),并且没有人改变不锁定的锁状态的最重要的事情。

如果消费者首先被调用,那么它会发现队列为空,并且它将等待。没有一刻当制片人可以在滑,一个产品添加到队列,然后通知锁,直到消费者准备接收该通知。

在另一方面,如果生产者首先调用,那么消费者保​​证不会调用wait()。

在消费的循环是两个重要的原因:其一是,如果有一个以上的消费者线程,那么它有可能为一个消费者到收到通知,但是另一个消费者钻进和从窃取的产品队列中。唯一合理的事情拳头消费者做在这种情况下是再等待下一个产品。该循环是很重要的另一个原因是,Javadoc中说的Object.wait()是允许的对象没有被告知,即使返回。这被称为虚假唤醒,而正确的方法来处理它是回去再等待。

另外请注意:该锁是私人和队列私人。这保证没有其他编译单元会干扰这个编译单元同步。

和注意事项:该锁是从队列本身不同的对象。这保证了在这个编译单元同步将不会与该队列实现做什么,同步(如果有的话)。

干扰

注:我的例子重新发明了轮子,以证明这一点。在现实code,你会使用put()和take()的ArrayBlockingQueue这将采取所有的等待和通知的照顾你的方法。

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

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

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.

On the other hand, if the producer is called first, then the consumer is guaranteed not to call 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.

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.

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

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.