CountDownLatch:对象在 wait() 之前未被线程锁定

CountDownLatch: object not locked by thread before wait()

我想暂停主线程直到另一个线程完成。 我尝试了 CountDownLatch 和信号量。但其中 none 有效。我得到了同样的错误。

Caused by: java.lang.IllegalMonitorStateException: object not locked by thread before wait()

代码

 public void testCountDownLatch(){
    final CountDownLatch countDownLatch = new CountDownLatch(1);
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                countDownLatch.countDown();
                //Toast.makeText(MainActivity.this, "Latch Released", Toast.LENGTH_SHORT).show();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();

    try {
        countDownLatch.wait();
        Toast.makeText(this, "Yes! I am free now", Toast.LENGTH_SHORT).show();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

我尝试搜索了几个小时,并且能够理解错误的原因(wait() 不知道 countdown() 是否在它之前被调用,在那种情况下它会永远等待)但我无法理解如何修复它:(

你用错了方法。您应该调用 await,而不是 wait。请参阅 CountDownLatch 示例代码。

结论

您忘记了 start 线程,所以异常很明显。

object not locked by a thread before wait()

发生的事情是直接调用 wait() 而没有调用 countdown() 方法(因为线程没有启动)所以它抛出 IllegalMonitorStateException 否则你的程序会等待你的一辈子不让你知道

解决方案

只需在线程上调用 start() 方法。

new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                countDownLatch.countDown();
                Toast.makeText(MainActivity.this, "Latch Released", Toast.LENGTH_SHORT).show();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();

您调用了错误的方法。您需要使用 await() 而不是 wait().

wait() is a method from Object and that method requires to synchronize over that object. Other synchronizers are normally preferred over Object#wait. Objects locked with Object#wait can be woken up with Object#notify or Object#notifyAll.

await() is a method of CountDownLatch and it waits for the CountDownLatch to count down (using CountDownLatch#countDown) 到 0.

如果你使用Semaphore (basically the opposite of CountDownLatch), you can aquire (increase the count of the semaphore by 1 if its limit has not been reached yet) it with Semaphore#aquire and release (decrese the count of the semaphore) with Semaphore#release.

除此之外,您似乎正在开发 Android 应用程序。您应该从不 阻塞Android 应用程序的主线程(或任何图形应用程序的UI 线程)as this will block your UI and result in Application not responding notices。阻止 UI(线程)意味着您的应用不会响应任何 UI 事件(例如用户点击按钮)。如果你需要做阻塞的事情,你应该在 background/worker 线程中做。出于这个原因,您还应该避免在主线程中执行 IO 操作(android 甚至会阻止主线程中的网络操作)。

1.The 线程应该开始 2.It 应该等待而不是等待。