Каждый корректный метод блокировки объявляет проверенное исключение InterruptedException
, которое служит именно этой цели: уведомить, что поток был прерван во время его блокировки.
Вы должны перехватить это исключение,и на самом деле это может заменить ваше поле stop
.
Например, давайте рассмотрим систему ведения журналов, которая будет записывать сообщения в файл в выделенном потоке (чтобы время, потраченное на ввод-вывод, не влияло на ваше приложение.- при условии, что он не слишком тяжелый IO).
Каждый поток имеет флаг initerrupted , который можно прочитать через Thread.currentThread().isInterrupted()
.Вы пытаетесь сделать что-то вроде этого:
class Logger {
private final File file = ...;
private final BlockingQueue<String> logLines = new LinkedBlockingQueue<String>();
private final Thread loggingThread = new Thread(new Runnable(){
@Override public void run() {
PrintWriter pw;
try {
pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));
while (!Thread.currentThread().isInterrupted()) {
try {
pw.println(logLines.take());
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // good habit: make sure the interrupt status is set
}
}
pw.flush();
pw.close();
} catch (IOException e) { ... flush and close pw if not null and open ... }
}
});
{ loggingThread.start(); }
public void log(final String line) { logLines.offer(line); } // will always work, because logLines is a LinkedBQ.
public void stop() { loggingThread.interrupt(); }
}
Наконец, для корректного завершения работы вашего приложения вы должны обязательно завершить этот поток, прежде чем разрешить JVM завершить работу.Для этого вы должны быть абсолютно уверены в том, что вызовете stop()
перед выключением любым возможным способом, или вы можете зарегистрировать перехват выключения, добавив что-то вроде этого инициализатора экземпляра в класс:
class Logger {
...
{
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override public void run() { close(); }
}));
}
}
Это заставит JVM вызвать close () (поэтому прерывает поток, очищает и закрывает файл) перед завершением.