Java 执行在同步块之间卡住
我有一段代码:Java 执行在同步块之间卡住,java,multithreading,Java,Multithreading,我有一段代码: 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 { w
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
接口的Downloader
类,其run()
方法如下所示:
@Override
public void run() {
synchronized (this) {
//work...
notify();
}
}
现在,这是有意的,有时。不过,大多数时候,它似乎卡在第二个同步块中(它总是通过第一个块)
我做错什么了吗
我是否也有一些概念上的错误,例如,这个实现没有给我任何优于单个线程的优势 在线程
对象上调用wait()
,但在下载程序
对象上调用notify()
因此,后台线程应该毫无问题地运行(尽管完全不同步),并且主线程应该总是在第一个synchronized
块中无限阻塞,因为没有人来唤醒它
这种情况的特殊之处在于,您在线程
对象本身上调用了wait()
,这是不鼓励的(我的真正意思是:禁止)。当线程终止时,它会在自身上调用notifyAll()
,因此当workerA
完成时,您将退出第一个synchronized
块。但是当到达第二个synchronized
块时,workerB
已经完成,因此第二个wait()
将永远不会结束
是否存在概念上的错误取决于您试图实现的目标。从代码上看,它看起来非常像您试图做的是后台线程。为什么它不总是阻塞呢?有时,它能很好地通过。。。是的,我想我最终需要在这里加入,但是如果我在
Downloader
对象上调用wait()stuck@Innkeeper这是一个很好的问题,为什么它不总是阻塞,它应该阻塞,我怀疑它会阻塞。即使你调用了正确的wait()
,它也会被卡住的原因更容易解释:背景线程可能已经完成,并且在遇到wait()
时已经调用了notify()
。嗯,它肯定是在使用join()
,所以我想这就是我想要的,谢谢!如果我连接两个worker而不是两个synchronized
块,它们将并行执行,因此这是一个使用多线程的有效位置,对吗?是的,join()
在这种情况下很好,但我可能会使用一个,它正是为此目的而设计的。我肯定不会使用手动创建的线程
s(除非是培训练习),而是使用执行器
s。好吧,我知道更高层次抽象的存在,我只想从经典开始。谢谢