1. ホーム
  2. java

[解決済み】 java.lang.IllegalMonitorStateException: オブジェクトはwait()の前にスレッドによってロックされていない?)

2022-02-13 17:34:37

質問

私は進行状況ダイアログを使用しています。私は、ユーザーが進行状況ダイアログを閉じたときにスレッドを停止する必要があります。残念ながらそれは例外pls私を与える。

内部クラスで

プレ 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()? これは重要なことです。なぜなら、もしnotifyの呼び出しが先に起こると、fooオブジェクトはnotifyされたことを思い出さないからです。 もし notify() がひとつだけで、それが wait() よりも前に起こったなら、wait() は決して戻ってきません。

waitとnotifyの使い分けは、こんな感じです。

プレ foo.wait()

この例で最も重要なことは、条件に対する明示的なテスト(すなわち、q.peek() != null)があることと、ロックをかけずに誰も条件を変更しないことです。

もしコンシューマが最初に呼ばれたなら、キューが空であることがわかり、待つことになります。 生産者が忍び込んで、キューに製品を追加し、消費者がその通知を受け取る準備ができるまで、ロックを通知できる瞬間はないのです。

一方、producerが先に呼ばれた場合、consumerはwait()を呼ばないことが保証されています。

コンシューマでのループは2つの理由で重要である。 ひとつは、もし複数のコンシューマースレッドがある場合、あるコンシューマが通知を受け取った後、別のコンシューマがこっそりキューからProductを盗むことがあり得るということです。 このような場合、最初の消費者がする唯一の合理的なことは、次の商品を再び待つことです。 ループが重要であるもう一つの理由は、Javadocによると、オブジェクトが通知を受けていないときでもObject.wait()を返すことが許されていることです。 これは「スプリアスウェイクアップ」と呼ばれ、正しい処理方法は、戻ってもう一度待つことです。

また、注意点として、ロックは 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); }

private


private