我有这段代码:
Profile a = randomProfile();
Thread workerA = new Thread(new Downloader(a));
workerA.start();
Profile b = randomProfile();
Thread workerB = new Thread(new Downloader(b));
workerB.start();
synchronized (workerA) {
try {
workerA.wait();
} catch (InterruptedException e) {
System.out.println("Error on background thread!");
System.exit(1);
}
}
synchronized (workerB) {
try {
workerB.wait();
} catch (InterruptedException e) {
System.out.println("Error on background thread!");
System.exit(1);
}
}
还有一个实现 Runnable
接口(interface)的 Downloader
类,其 run()
方法如下所示:
@Override
public void run() {
synchronized (this) {
//work...
notify();
}
}
现在,有时这会按预期工作。但大多数时候,它似乎卡在第二个同步块(synchronized block)中(它总是通过第一个同步块(synchronized block))。
我做错了什么吗?
我还有一些概念错误,例如与单线程相比,这个实现没有给我带来任何优势吗?
最佳答案
wait()
在 Thread
对象上调用,但 notify()
在 Downloader
上调用> 对象。
因此,后台线程应该毫无问题地运行(尽管完全不同步),并且主线程应该始终在第一个synchronized
block 中无限阻塞,因为没有人可以唤醒它。
这种情况的特殊之处在于,您在 Thread
对象本身上调用了 wait()
,这是不鼓励的(我的真正意思是:禁止)。当线程终止时,它会自行调用 notifyAll()
,因此当 workerA
完成时,您将退出第一个 synchronized
block 。但当到达第二个 synchronized
block 时,workerB
已经完成,因此第二个 wait()
将永远不会结束。
是否存在概念错误取决于您想要实现的目标。从代码来看,它看起来非常像您尝试做的事情是 join()
后台线程。
关于java - 执行在同步块(synchronized block)之间卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26876347/