我有以下代码:
synchronized void myMethod() {
String s="aaa";
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
代码抛出异常... 我已经看到在线程上使用 wait 方法的代码,这是可以 self 解释和合乎逻辑的。
- 为什么要在字符串这样的对象上使用 wait 方法而不是在主线程上使用它?
- 它有什么用?
- 有这样的实际实现吗?
提前致谢
最佳答案
您的示例代码将无法运行,因为该方法在调用 myMethod 的实例上同步,而在字符串上调用 wait。它会导致 IllegalMonitorStateException . 您必须在锁定的同一个对象上调用 wait 和 notify。得到通知的线程是那些等待调用 notify 的锁的线程。
锁定字符串对象是个坏主意,不要这样做。您不想锁定无法推断出谁可以获得它们的东西,因为任何人 都可以获得它们。应用程序其他地方的一些其他代码可能会锁定相同的字符串值,并且您可能会出现奇怪的交互、死锁,因为其他代码正在锁定您,或者让其他代码通知您。在调试某些多线程行为时,您是否需要考虑字符串是如何合并的?
您可以通过定义自己的锁并将其设为私有(private)来限制谁可以获得您的锁,如下所示:
private final Object LOCK = new Object();
因此只有调用您正在控制访问的对象的方法的线程才能获取锁:
public void myMethod() {
synchronized(LOCK) {
...
}
}
这样您就可以确切地知道什么可以获取锁,它并不是对应用程序中的每个线程都可用。任何可以引用该对象的对象都可以获取锁,因此请将引用保持为私有(private)。
您的示例在没有带条件变量的循环的情况下使用等待的方式非常可疑。线程可以在没有得到通知的情况下退出等待调用。即使通知了线程,调度程序也不会给予它任何特殊优先级。另一个线程可以闯入并做一些事情,可能会影响通知正在提醒等待线程的状态,在线程被通知的时间和线程可以重新获取它开始等待时放弃的锁的时间之间。由于这两个原因,需要有一个循环,线程从等待中醒来时重新测试条件。
此外,如果“在线程上使用等待方法的代码”是指将 Thread 对象用作锁的代码,那是另一件要避免的事情,请参阅 API documentation for Thread#join :
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
关于java - 为什么要对字符串或其他对象使用 wait 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25295756/