В листинге 7.15 «Параллелизма Java на практике» есть пример производителя / потребителя без ожидания завершения при остановке метода.
Основной поток в исходном коде не ожидает завершения потока журнала. Это может вызвать проблемы, особенно при входе в файл, и файл необходимо манипулировать после остановки. Исключение может быть сгенерировано, если потребитель все еще использует файл.
Работает ли следующий код, добавляя ожидание завершения с таймаутом для метода stop?
public class LogService {
private final BlockingQueue<String> queue;
private final LoggerThread loggerThread;
private final PrintWriter writer;
private final Object lock;
private boolean shutdown;
private boolean prepareShutdown;
private int reservations;
public LogService(Writer writer) {
this.queue = new LinkedBlockingQueue<String>();
this.loggerThread = new LoggerThread();
this.writer = new PrintWriter(writer);
this.lock = new Object();
}
public void start() {
loggerThread.start();
}
public void stop(long timeout) throws InterruptedException {
synchronized (lock) {
prepareShutdown = true;
}
loggerThread.interrupt();
try {
loggerThread.join(timeout);
} finally {
synchronized (lock) {
shutdown = true;
}
loggerThread.interrupt();
}
}
public void log(String msg) throws InterruptedException {
synchronized (lock) {
if (shutdown || prepareShutdown)
throw new IllegalStateException(/* ... */);
++reservations;
}
queue.put(msg);
}
private class LoggerThread extends Thread {
public void run() {
try {
while (true) {
try {
synchronized (lock) {
if (shutdown || prepareShutdown
&& reservations == 0)
break;
}
String msg = queue.take();
synchronized (lock) {
--reservations;
}
writer.println(msg);
} catch (InterruptedException e) { /* retry */
}
}
} finally {
writer.close();
}
}
}
}