java.lang. IllegalSystemorStateException:在wait()之前线程没有锁定对象?

rsl1atfo  于 2024-01-05  发布在  Java
关注(0)|答案(3)|浏览(95)

我正在使用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();
            }
        }
    }
}

字符串
Oncreate:

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

ubby3x7f

ubby3x7f1#

这是错误的:

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

字符串
问题是,什么会唤醒这个线程呢?也就是说,你如何保证在第一个线程调用foo.wait()之前,其他线程不会调用foo.notify()?这一点很重要,因为如果notify调用先发生,foo对象将不会记住它被通知了。如果只有一个notify(),并且它发生在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),并且没有人在不锁定锁的情况下更改条件。
如果消费者首先被调用,那么它会发现队列是空的,它会等待。生产者没有时间可以溜进来,将Product添加到队列中,然后通知锁,直到消费者准备好接收该通知。
另一方面,如果首先调用生产者,那么消费者保证不会调用wait()。
消费者中的循环很重要,原因有二:一个是,如果有多个消费者线程,那么一个消费者可能会收到通知,但是另一个消费者偷偷地从队列中偷走了Product。在这种情况下,第一个消费者要做的唯一合理的事情就是再次等待下一个Product。循环很重要的另一个原因是Javadoc说Object.wait()被允许返回,即使对象没有被通知。这被称为“虚假唤醒”,正确的处理方法是返回并再次等待。
另请注意:锁是private,队列是private。这保证了没有其他编译单元会干扰这个编译单元中的同步。
注意:锁是一个不同于队列本身的对象。这保证了这个编译单元中的同步不会干扰队列实现所做的任何同步(如果有的话)。
注意事项:我的例子重新发明了一个轮子来证明一个观点。在真实的代码中,你会使用ArrayBlockingQueue的put()和take()方法,它会为你处理所有的等待和通知。

c3frrgcw

c3frrgcw2#

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

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

字符串
……但我不知道你想用这些锁做什么。

llew8vvj

llew8vvj3#

看起来你真的是在尝试使用synchronizedwait,而你不应该这样做。
如果您真的想等待线程完成,您应该这样做
在您的UpdateThread中:

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

字符串
在你的作品中:

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


在你的解雇:

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


注意,我给你的线程添加了一个退出条件,这样它就会停止(实际上,你的线程会继续运行)。你可能想让退出条件私有化,并添加一个setter来保持干净。另外,我使用join来正确地等待你的线程完成。

相关问题