我正在尝试使用多线程解决Java中编写者偏好的读者 - 编写者问题。以下是我的代码所做的精简版本。它会起作用吗?
public PriorityBlockingQueue<myClass> pq;
public void foo(){
myClass obj = new myClass();
pq.add(obj);
obj.wait();
//Actual code
}
public void bar(){
pq.remove().notify();
}
假设优先级队列pq最初为空,并且封闭类的构造函数调用pq的构造函数。此外,foo首先由一个线程调用,然后由另一个线程调用。因此,当调用foo时,它会将obj添加到队列中,并成为前端元素,以便在bar中调用remove时删除的元素。我的问题是,“实际代码”会被执行吗?或者我在两个完全不同的对象上执行wait()和notify()?如果是这样,我该如何解决?
答案 0 :(得分:0)
我可以看到的主要问题是线程可以虚假唤醒......所以你应该总是有一些与条件相关的数据。 notifyAll()也不太可能导致死锁...所以:
public void foo() {
MyClass obj = new MyClass();
pq.add(obj);
synchronized(obj) {
while (!obj.isDoneBeingProcessed()) {
obj.wait();
}
}
}
public void bar() {
MyClass next = pq.remove();
if (!next) {
return;
}
next.doProcessing();
synchronized(next) {
next.setDone(true);
next.notifyAll();
}
}
但请注意,此代码实际上没有意义,因为它基本上序列化了整个计算。如果你在一个线程中排队所有内容,而在另一个线程中你进行处理,然后......只在最后或另一个线程试图等待所有内容,这将更有意义。在生成所有内容之前将等待放入生产者阶段会有效地序列化整个计算。