Когда я создаю поток путем вызова ScheduledExecutorService.schedule (), он никогда не завершается после выполнения запланированной задачи.
Например, следующая программа никогда не выходит:
public static void main(String[] args) {
ScheduledFuture scheduledFuture =
Executors.newSingleThreadScheduledExecutor().schedule(new Callable() {
public Void call() {
doSomething();
return null;
}
}, 1, TimeUnit.SECONDS);
}
public static void doSomething() {
}
Действительно ли это - ошибка JDK, или я просто пропускал что-то?
Чтобы остановить выполнение, необходимо вызвать scheduleExecutorService.shutdown ()
. В противном случае он перезапускается каждую секунду.
(ИЗМЕНИТЬ: см. Комментарии)
Запланированная задача либо выполняется, либо ожидает выполнения.
Если задача ожидает выполнения, future.cancel()
предотвратит ее выполнение (оба варианта cancel(true)/cancel(false)).
Если задача уже выполняется, future.cancel(false)
не будет иметь никакого эффекта. future.cancel(true)
прервет поток, выполняющий эту задачу. Будет ли это иметь какой-либо эффект, зависит от вас, кто будет реализовывать эту задачу. Задача может реагировать или не реагировать на прерывание в зависимости от реализации.
Для того чтобы ваша задача реагировала на отмену, вы должны реализовать doSomething()
, чтобы она реагировала на прерывание.
Есть два основных способа сделать это:
1.Проверить флаг прерывания в вашей логике
public void doSomething(){
stuff();
//Don't use Thread.interrupt()
if(Thread.currentThread().isInterrupted()){
// We have an interruption request, possibly a cancel request
//Stop doing what you are doing and terminate.
return;
}
doLongRunningStuff();
}
Вы должны время от времени проверять флаг прерывания, и если вас прервали, остановить то, что вы делаете, и вернуться. Для проверки обязательно используйте Thread.isInterrupted(), а не Thread.interrupt().
2.Действовать при прерванном исключении
public void doSomething(){
try{
stuff();
}catch(InterruptedException e){
// We have an interruption request, possibly a cancel request
// First, preserve Interrupted Status because InterruptedException clears the
// interrupted flag
Thread.currentThread.interrupt();
// Now stop doing your task and terminate
return;
}
doLongRunningStuff();
}
Когда у вас есть метод, который выбрасывает исключение InterruptedException, убедитесь, что вы остановили свои действия и прервали их, когда оно было выброшено.
Как только вы реализуете свои методы таким образом, вы сможете вызывать future.cancel(true) для отмены выполнения запущенной задачи.