우선 읽는 것을 좋아하지 않는 녀석들에 의한 마크 질문을 막기 위해 나는 Producer-Consumer Logging service with Unreliable way to shutdown 질문을 읽었다. 그러나 질문과 대답이 책 본문과 모순되는 것에 대해서는 완전히 대답하지 않습니다. 이제 우리는이 프로세스를 중지하는 방법을 이해하기 위해해야 LogWriter의 경쟁 조건으로 인해 제작자가 차단 될 수 있습니까? [연습 동시성]
public class LogWriter {
private final BlockingQueue<String> queue;
private final LoggerThread logger;
private static final int CAPACITY = 1000;
public LogWriter(Writer writer) {
this.queue = new LinkedBlockingQueue<String>(CAPACITY);
this.logger = new LoggerThread(writer);
}
public void start() {
logger.start();
}
public void log(String msg) throws InterruptedException {
queue.put(msg);
}
private class LoggerThread extends Thread {
private final PrintWriter writer;
public LoggerThread(Writer writer) {
this.writer = new PrintWriter(writer, true); // autoflush
}
public void run() {
try {
while (true)
writer.println(queue.take());
} catch (InterruptedException ignored) {
} finally {
writer.close();
}
}
}
}
: 책에서
다음 코드를 제공했다. 로깅을 중지해야하지만 이미 커밋 된 메시지를 건너 뛰지 않아야합니다.
저자는 접근 방법 연구 :
public void log(String msg) throws InterruptedException {
if(!shutdownRequested)
queue.put(msg);
else
throw new IllegalArgumentException("logger is shut down");
}
을하고 이런 식으로 코멘트 :
LogWriter를 종료하는 또 다른 방법은 플래그가되는 것을 더 메시지를 방지하기 위해 "요청 종료"를 설정하는 것입니다 목록 7.14와 같이 이 제출됩니다. 소비자는 셧다운이 요청되었음을 통보 받으면 대기열을 으로 유출하고, 대기중인 메시지를 모두 털어 내고 을 차단 한 모든 생산자를 차단 해제한다. 그러나이 접근 방식은 경쟁 조건이 있으므로 신뢰할 수 없습니다. 로그 구현은 check-then-act 시퀀스입니다. 프로듀서는 서비스가 아직 종료되지 않았 음을 관찰 할 수 있습니다. 생성자가 로그에 결코 차단되지 않을 수도있는 차단 해제된다. 소비자가 대기열이 고갈되었다고 선언하기 전에 몇 초 기다리는 것과 같은 이럴 가능성을 줄이는 트릭이 있습니다. 그러나 이들은 근본적인 문제를 변경하지 않으며 단지 장애가 발생할 가능성이 높습니다 ( ).
나를 위해 충분한 문구가 있습니다.
나는
if(!shutdownRequested)
queue.put(msg);
원자하지 않고 메시지를 shutdowning 후 큐에 추가 할 수 있음을 이해합니다. 예, 정확하지는 않지만 문제는 없습니다. 큐가 방류 될 때 큐가 비게 될 때 우리는 LoggerThread를 멈출 수 있습니다. 특히 생산자가 차단 될 수있는 이유를 모르겠다.
작성자가 전체 코드를 제공하지 않아서 모든 세부 사항을 이해할 수 없습니다. 나는이 책이 지역 사회 대다수에 의해 읽혔다 고 믿는다. 그리고이 예는 상세한 설명을 가지고있다.
전체 코드 예제로 설명하십시오.
같은 두 줄의 코드 사이에서 1000 개의 스레드가 기다리고있을 것으로 예상됩니다. 비록 그것이 이론적으로 가능하다면 여전히 기술적으로 부정확하다는 것을 깨달을지라도. – shmosel
종료 프로세스가 큐 * 및 모든 차단 된 생산자 *를 실제로 소진하는 방법을 보여줄 수 있는지 알고 싶습니다. 테스트에서'drainTo()'는 이미 대기중인 항목 만 배출합니다. – shmosel
@shmosel 동의합니다. 그것은 조금 멀리 가져 왔지만 당신이 내 대답을 오해했다고 생각합니다. 1000 개의 스레드는'put '을 기다리지 않습니다. 그것은 대기중인 1001 번째 스레드입니다. 'put '을 막으려면 큐에 1000 개의 요소가 있어야하고 1001 번째 블록에는 새로운 요소를 넣으려고합니다. 1001 스레드가 큐에 새 요소를 넣으려고 시도 할 경우에만 가능할 수있는 1001 번째 요소에 대한 공간을 소비자가 확보하지 못하도록 보장하면서 ** 모든 소비자가 큐를 비우는 것을 끝내고 이제는 while 루프. 그 단락을 설명 할 다른 방법이 보이지 않습니다! 너? – CKing