Как остановить весь runnable поток в классе java-исполнителя?

final ExecutorService executor = Executors.newFixedThreadPool(1);
final Future<?> future = executor.submit(myRunnable);
executor.shutdown();
if(executor.awaitTermination(10, TimeUnit.SECONDS)) {
  System.out.println("task completed");
}else{
  System.out.println("Executor is shutdown now");
}

//MyRunnable method is defined as task which I want to execute in a different thread.

Вот метод run класса исполнителя:

public void run() {
try {
     Thread.sleep(20 * 1000);
} catch (InterruptedException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
}}

Здесь он ждет 20 секунды, но когда я запускаю код, он выдает исключение:

java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)

Я не могу закрыть совпадающий поток в Java Executor class. Вот мой поток кода:

  • Создал новый поток с Java-исполнителем для запуска некоторой задачи, написанной в MyRunnable
  • executor подождите 10 секунд для выполнения задач.
  • Если задача завершена, то завершаемый поток также завершается.
  • Если задача не завершена в течение 10 секунд, тогда класс executor должен прекратить поток.

Все работает отлично, за исключением завершения задач в последнем сценарии. Как я должен это делать?

Ответ 1

Метод shutDown() просто препятствует планированию дополнительных задач. Вместо этого вы можете вызвать shutDownNow() и проверить прерывание потока в Runnable.

// in your Runnable...
if (Thread.interrupted()) {
  // Executor has probably asked us to stop
}

Пример, основанный на вашем коде, может быть:

final ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
  public void run() {
    try {
      Thread.sleep(20 * 1000);
    } catch (InterruptedException e) {
      System.out.println("Interrupted, so exiting.");
    }
  }
});

if (executor.awaitTermination(10, TimeUnit.SECONDS)) {
  System.out.println("task completed");
} else {
  System.out.println("Forcing shutdown...");
  executor.shutdownNow();
}

Ответ 2

Как правило, это плохая идея прекратить выполнение потока извне, потому что вы не знаете состояние, в котором в данный момент находится поток. Возможно, что ему нужно сделать некоторые очистки, и он не сможет сделайте это, когда вы принудительно отключите его. Вот почему все методы Thread, которые делают это, отмечены как устаревшие.

Намного лучше использовать один из многих методов, доступных для межпроцессной связи, чтобы сигнализировать о запущенной в самом потоке процедуре, чтобы она прервала свою работу и вышла нормально. Один из способов сделать это - добавить метод abort() к вашему runnable, который вызывает флаг, объявленный как volatile. Внутренняя петля вашего Runnable проверяет этот флаг и выходит (контролируемым образом) при поднятии этого флага.