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 应该等待而不是等待。
我想暂停主线程直到另一个线程完成。
我尝试了 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 应该等待而不是等待。