use*_*065 1 java multithreading wait
我有以下代码:
synchronized void myMethod() {
String s="aaa";
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
代码抛出异常...我已经看到在线程上使用wait方法的代码,这是自我解释和逻辑的..
提前致谢
您的示例代码将无法工作,因为该方法正在调用myMethod的实例上进行同步,而在字符串上调用wait.它将导致IllegalMonitorStateException.您必须在您锁定的同一对象上调用wait并通知.获得通知的线程是等待锁定的线程,通知被调用.
锁定字符串对象是一个坏主意,不要这样做.你不想锁定那些你无法解释谁可以获得它们的东西,因为任何人都可以获得它们.应用程序中其他地方的一些其他代码可能会锁定相同的字符串值,并且您可能会发生奇怪的交互,因为其他代码正在锁定,或者其他代码通知您,因此会发生死锁.在调试某些多线程行为时,您是否想要考虑字符串的汇总方式?
您可以通过定义自己的锁并将其设为私有来限制谁可以获取锁定,如下所示:
private final Object LOCK = new Object();
Run Code Online (Sandbox Code Playgroud)
因此,只有调用您正在控制访问的对象的方法的线程才能获取锁:
public void myMethod() {
synchronized(LOCK) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
这样你就知道什么可以获得锁,它不适用于应用程序中的每个线程.可以通过任何可以获取对该对象的引用来获取锁,因此保持引用为私有.
您的示例使用wait而没有带有条件变量的循环的方式非常可疑.线程可以在没有得到通知的情况下退出等待的调用.即使通知了一个线程,也不会给调度程序任何特殊的优先级.另一个线程可以插入并执行某些操作,可能会影响通知警告等待线程的状态,在通知线程的时间和线程可以重新获取它在开始等待时放弃的锁定的时间之间.由于这两个原因,需要有一个循环,当线程从等待中唤醒时,线程重新测试一个条件.
另外,如果"使用线程上的等待方法的代码"是指将Thread对象用作锁的代码,这是另一件要避免的事情,请参阅Thread#join的API文档:
此实现使用this.wait调用this.isAlive的循环.当一个线程终止时,将调用this.notifyAll方法.建议应用程序不要在Thread实例上使用wait,notify或notifyAll.