我正在尝试创建一个SingleBlockingQueue<T>
同步器,它允许一个线程将offer()
一个元素给它,而另一个线程将它take()
它。一次只有一个T
元素被保存在SingleBlockingQueue<T>
内部,并且如果前一个元素正在等待其线程为take()
,则推送线程在offer()
上被阻止。推动线程将继续推送物品,直到它调用setComplete()
,并且线程将继续呼叫take()
而isComplete()
为假。如果线程正在等待某个元素,它将被阻塞。创建SingleBlockingQueue同步器
这是我到目前为止的同步器。
import java.util.concurrent.atomic.AtomicBoolean;
public final class SingleBlockingQueue<T> {
private volatile T value;
private final AtomicBoolean isComplete = new AtomicBoolean(false);
private final AtomicBoolean isPresent = new AtomicBoolean(false);
public void offer(T value) throws InterruptedException {
while (isPresent.get()) {
this.wait();
}
this.value = value;
synchronized(this) {
this.notifyAll();
}
}
public boolean isComplete() {
return !isPresent.get() && isComplete.get();
}
public void setComplete() {
isComplete.set(true);
}
public T take() throws InterruptedException {
while (!isPresent.get()) {
this.wait();
}
T returnValue = value;
isPresent.set(false);
synchronized(this) {
this.notifyAll();
}
return returnValue;
}
}
这里是科特林
val queue = SingleBlockingQueue<Int>()
thread {
for (i in 1..1000) {
queue.offer(i)
}
queue.setComplete()
}
thread {
while (!queue.isComplete) {
println(queue.take())
}
}
Thread.sleep(100000)
不过,我得到一个错误的使用例子,我在我头上了一下,在这一点上。感谢RxJava,我很久没有做同步器。我究竟做错了什么?
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.swa.rm.common.util.SingleBlockingQueue.take(SingleBlockingQueue.java:29)
at RxOperatorTest$testSingleBlockingQueue$2.invoke(RxOperatorTest.kt:33)
at RxOperatorTest$testSingleBlockingQueue$2.invoke(RxOperatorTest.kt:8)
at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:18)
不应该等待()在同步块内调用吗? –
我试过,但有同样的问题。也许我需要创建两个独立的锁?另外,对于我之前写过的同步器没有这样做,也没有任何问题。 https://github.com/thomasnield/tom-sync/blob/master/src/main/java/org/nield/concurrency/BufferedLatch.java – tmn
github代码给出了同样的错误,如果我直接调用await()[Just尝试在我当地的日食]。在调用await()之前,您可能会在与该对象关联的监视器上锁定一个锁。 –