многие «блокируют, пока что-то не происходит» методы (такие как java.lang.Thread
'wait
метод) имеют перегруженный вариант, в котором можно указать время ожидания. Однако большинство методов ввода / вывода (например, nextLine
сканера или read
входного потока) не делают.
Спецификация этих типов указывает на то, что они являются прерывистыми или нет намеренно не определены; java хочет работать на как можно большем количестве платформ, а наименьший общий знаменатель - «нет, не прерываемый», поэтому он указан именно таким образом.
Однако на большинстве платформ да, вы может прервать его.
Таким образом, решение:
Запустите второй поток, передайте ему ссылку на ваш поток и скажите, чтобы он прерывал этот поток по истечении определенного времени.
Поток, который прерывается, просто «поднимает флаг прерывания», ничего более (вы можете проверить с помощью if (Thread.interrupted()) ...;
, если хотите, который также очищает этот флаг. Однако, различные методы, встроенные в java, будут немедленно выход, если вы вызываете их, когда этот флаг поднят, и будет отменен на месте, если вы поднимите флаг, когда они блокируют.
Любой метод, который объявлен для выброса InterruptedException
, например Thread.sleep
, равен гарантированно будет иметь такое поведение. Любой другой метод блокировки может или не может (вернуться ко всему этому «общему знаменателю всех платформ java работает на»). Другими словами , поскольку вы не совсем знаете, где будет находиться ваш код, вам нужно иметь дело с различными сценариями ios. Что, если прерывание происходит, когда вы ожидаете ввода (скорее всего, readLine завершается броском чего-то, что вы можете поймать), что если оно происходит сразу после (этот флаг будет установлен; вам нужно очистить его в какой-то момент ) и как вы 'отменяете отмену' - если пользователь печатает, вы хотите, чтобы этот тикающий поток бомб с часовым механизмом закончился сам. Вы можете сделать это, просто установив переменную, которую проверяет поток временной бомбы, даже если он проверяет ее только после истечения времени (Время истекло! О, поток, который я должен прервать, когда-то сказал мне, пока я ждал тайм-аута, который это больше не нужно, поэтому я просто закончу сейчас).
Все довольно сложно. Может быть, есть какая-то библиотека, чтобы сделать это намного проще для вас, но я лично не знаю о ней.
public class InterruptMeThread extends Thread {
private final Thread interruptMe;
private final long millis;
private volatile boolean nevermind;
public InterruptMeThread(Thread interruptMe, long millis) {
this.interruptMe = interruptMe;
this.millis = millis;
}
@Override public void run() {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
// Who interrupts the interruptors? Let's assume this means
// my interruption services are no longer desired and exit.
return;
}
if (!nevermind) interruptMe.interrupt();
}
public void nevermind() {
this.nevermind = true;
Thread.interrupted(); // clear the flag if it is raised.
}
и используется:
InterruptMeThread imt = new InterruptMeThread(Thread.currentThread(), 10000);
imt.start();
try {
reader.nextLine();
} catch (IOException e) {
// you'd have to test what kind of exception falls out of interrupted...
// but something will.
// for now, to debug it so we can see it...
throw new RuntimeException(e); // or just let it bubble up, either way works.
}
imt.nevermind();