Существует поток, который подключается к серверу (HTTP) и ожидает ответа или таймаута ответа (сервер не отвечает, пока он не вернет данные) в цикле. В случае, если ответ вернул обработку потока.Безопасное прерывание потока в Java
При остановке обслуживания необходимо остановить/прервать все потоки, но потоки должны завершить обработку ответа (в случае, если поток обрабатывается, а не только ожидает ответа).
Вот пример кода
public class WaitingResponseThread extends Thread {
static final int TIMEOUT = 4 * 1000;
static final int PROCESSING_DURATION = 2000;
private volatile boolean stopped = false;
private volatile boolean processing = false;
public void run() {
System.out.println("starting child thread");
while(!stopped) {
try {
// here a thread is awaiting server response (in real life response timeout is 400 sec)
// probably it is safe to interrupt the thread now
// emulating this with Thread.sleep()
System.out.println("awaiting response");
Thread.sleep(TIMEOUT);
processing = true;
// there is some job on response and we must allow it to finish the job
// again emulating delay with Thread.sleep()
Thread.sleep(PROCESSING_DURATION);
processing = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ending child thread");
}
public void setStopped(boolean stopped) {
this.stopped = stopped;
}
public boolean isProcessing() {
return processing;
}
public static void main(String[] args) {
WaitingResponseThread t = new WaitingResponseThread();
// starting thread, it sends a request and waits for a response
t.start();
try {
Thread.sleep(1);
// let's allow the thread to finish normally in case it is processing response
t.setStopped(true);
System.out.println("awaiting child thread to get response");
Thread.sleep(TIMEOUT + 1);
// let's allow the thread to finish processing
while(t.isProcessing()) {
System.out.println("processing");
Thread.sleep(500);
}
// we can't wait for 400sec until the next loop check
// so as the thread is sleeping we just interrupting it
if(t.isAlive()) {
System.out.println("killing");
t.interrupt();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ending main thread");
}
}
Является ли это "прерывание" метод хорошо? Есть ли другой способ не ждать до тех пор, пока время ожидания и не потерять обрабатываемые данные?
Постарайтесь посмотреть http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get(long,%20java.util.concurrent.TimeUnit) – DmitryKanunnikoff
альтернативой было бы использовать исполнителей https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html. Затем вы можете вызвать 'yourPool.shutdown()' и 'yourPool.awaitTermination (time, unit) ', но вам все равно придется обрабатывать прерывания в каждом потоке должным образом, и насколько я знаю, нет никакого чугунного способа гарантировать, что потоки всегда закончат правильно. Вместо того, чтобы изобретать колесо. – Neilos
Метод 'interrupt' не является хорошим выбором, если вы хотите завершить обработку текущих HTTP-запросов. Причина в том, что вызов 'interrupt' может вызвать [' InterruptedIOException'] (http://docs.oracle.com/javase/7/docs/api/java/io/InterruptedIOException.html) операций ввода-вывода в потоке, являющемся прерывание, прекращение попытки ввода-вывода (и HTTP-запросы включают IO) –