코드에서 BlockingQueue.take()
에 스레드가 차단되어있는 동안 this
의 잠금 장치를 누르고 있습니다. 코드가 동기화 된 블록을 벗어나거나 this.wait()
이 호출 될 때까지 잠금이 해제되지 않습니다.
여기서는 moveToFirst()
및 moveToSecond()
이 차단되어야하며 클래스가 모든 대기열 액세스를 제어한다고 가정합니다.
private final BlockingQueue<Object> firstQ = new LinkedBlockingQueue();
private final Semaphore firstSignal = new Semaphore(0);
private final BlockingQueue<Object> secondQ = LinkedBlockingQueue();
private final Semaphore secondSignal = new Semaphore(0);
private final Object monitor = new Object();
public void moveToSecond() {
int moved = 0;
while (moved == 0) {
// bock until someone adds to the queue
firstSignal.aquire();
// attempt to move an item from one queue to another atomically
synchronized (monitor) {
moved = firstQ.drainTo(secondQ, 1);
}
}
}
public void putInFirst(Object object) {
firstQ.put(object);
// notify any blocking threads that the queue has an item
firstSignal.release();
}
당신은 moveToFirst()
및 putInSecond()
비슷한 코드를 가지고있다. while
은 다른 코드가 항목을 대기열에서 제거 할 수있는 경우에만 필요합니다. 대기 행렬을 기다리는 대기열을 제거하는 메소드가 세마포어로부터 허가를 받아야하고, 세마포어가 공정한 세마포어로 작성되어야하므로 aquire
을 호출하는 첫 번째 스레드가 먼저 해제됩니다.
firstSignal = new Semaphore(0, true);
당신은 당신이
- 는
Executor
- 에 보낸
Runnable
에서 작업을해야합니까 방법을 가지고 몇 가지 옵션이 차단 moveToFirst()
에 타임 아웃을 전달하고를 사용하는 moveToFirst()
을하지 않으려면
BlockingQueue.drainTo(secondQ, 1)
을 사용하고 moveToFirst()
을 수정하여 성공했는지 여부를 나타내는 부울을 반환합니다.
위 세 가지 옵션의 경우 세마포어가 필요하지 않습니다.
마지막으로 나는 이동을 원자 적으로 만들 필요성에 의문을 제기합니다. 여러 스레드가 큐에 추가하거나 큐에서 제거하는 경우 관찰 큐는 moveToFirst()
이 원자인지 여부를 알 수 없습니다.
효율상의 이유로 Java 1.5 이상의 대기에서 잠금을 권장했습니다. Java 1.6에서는 거의 동일한 수준의 효율성을 제공합니다. 향후의 VM 최적화로 인해 대기/통지 구현이 더 빨라질 수 있습니다. –
그러나 잠금 장치를 올바르게 사용하는 것이 훨씬 쉽습니다. – JesperE
첫 번째 큐가 비어있는 OP 문제를 어떻게 해결할 수 있습니까? 코드는 여전히 take() 메소드에서 무기한 차단됩니다. – Adamski