Почему делает поток, запущенный ScheduledExecutorService.schedule (), никогда не завершаются?

Когда я создаю поток путем вызова 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, или я просто пропускал что-то?

12
задан oberlies 29 April 2014 в 10:43
поделиться

2 ответа

Чтобы остановить выполнение, необходимо вызвать scheduleExecutorService.shutdown () . В противном случае он перезапускается каждую секунду.

(ИЗМЕНИТЬ: см. Комментарии)

1
ответ дан 2 December 2019 в 21:22
поделиться

Запланированная задача либо выполняется, либо ожидает выполнения.

Если задача ожидает выполнения, 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) для отмены выполнения запущенной задачи.

7
ответ дан 2 December 2019 в 21:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: