Ниже приведен фрагмент кода
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
while (true) System.out.println("1");
});
executor.shutdown();
executor.shutdownNow();
Есть ли способы закрыть экзекьютор извне? (предполагаю, что нельзя изменить саму задачу) как убить -9 в линуксе
Нет, не изменив задачу, вы не сможете ее остановить.
Если поток представляет собой цикл, вы можете инвертировать управление: в конце цикла заставьте поток спрашивать, следует ли ему переходить к следующей итерации. Вы можете сделать это через переменную, файл, базу данных и т.д.
Все, что вы можете сделать с реальным кодом, — это «попытаться» остановить поток, выполняющий цикл. Если это основной поток, то вам нужно убить приложение.
Спасибо за ответ :)
в linux мы можем принудительно остановить процесс независимо от того, что это такое. поэтому мне интересно, есть ли в java механизм, подобный сигналу kill -9 в linux, чтобы принудительно остановить поток




Есть несколько способов
boolean shouldContinue, чтобы установка этого значения на false приводила к выходу из цикла в какой-то момент.Thread#stop (небезопасно) или Thread#interrupt (безопаснее).javaagent, что позволит вам делать то же самое, что и в пункте 2.Как 2, так и 3, с тщательной интеграцией, например, с сокетами, могут позволить вам сделать это в уже запущенном процессе извне, например. из командной строки
Только не забудьте использовать ключевое слово volatile в первом случае.
"предлагать не может изменить саму задачу"
@AndyTurner 3-й вариант тогда.
Почему бы вам не использовать ScheduledExecutorService вместо обычного ExecutorService?
Вы можете захватить Будущее, то есть задачу, которая выполняется (или будет) выполняться, и отменять ее «извне» по своему усмотрению.
public class Example {
private ScheduledFuture mThread;
private final ScheduledExecutorService mExecutor = Executors.newScheduledThreadPool(1);
public void executeForever() {
mThread = mExecutor.schedule(() -> { while (true) System.out.println("1"); }, 0, TimeUnit.NANOSECONDS);
}
public void cancelThread() {
mThread.cancel(true);
}
}
Ваш ScheduledFuture также унаследует все методы интерфейса Future, такие как cancel, get, isCancelled и isDone.
Дополнительная информация о ScheduledFuture: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledFuture.html
Дополнительная информация о ScheduledExecutorService: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html
И таким образом вам не нужно менять задачу, только способ ее выполнения.
Не этот конкретный фрагмент, я в основном сделал базовую реализацию того, что делает ScheduledExecutorService, почему вы говорите, что это не сработает? Обновлено: я только что заметил, что логический флаг для метода отмены требуется, чтобы уведомить, следует ли его отменить, даже если он запущен.
Пожалуйста, прочитайте javadoc для метода завершение работы (). Очень ясно сказано:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
Итак, что вам нужно сделать, это изменить отправленную задачу в коде, чтобы она реагировала на метод Thread.interrupt(). т.е. вам нужно изменить свою строку while (true)
на while (true && !Thread.currentTrhead().isInterrupted())
для более подробной информации прочитайте javadoc для Класс потока в конкретных методах interrupt(), interrupted() и isInterrupted()
Если вы раскрываете поток, в котором вас запускает исполнитель, вы можете прервать его. Для меня это печатает 1 только 4 раза, предполагая, что прерывание прошло успешно.
Помните, что это зависит от того факта, что Thread.sleep и System.out.println прерываемы. Если вы не проверяете Thread.isInterrupted (как они оба делают), вы все равно не сможете прервать поток.
ExecutorService executor = Executors.newSingleThreadExecutor();
private void test() throws InterruptedException {
AtomicReference<Thread> thread = new AtomicReference<>();
Future<Object> task = executor.submit(() -> {
// Keep track of the thread.
thread.set(Thread.currentThread());
try {
while (true) {
Thread.sleep(1000);
System.out.println("1");
}
} finally {
System.out.println("Interrupted: " + Thread.currentThread().isInterrupted());
}
});
Thread.sleep(5000);
// Interrupt the thread.
thread.get().interrupt();
Thread.sleep(5000);
System.out.println("Press <Enter> to shutdown");
new Scanner(System.in).nextLine();
executor.shutdown();
System.out.println("Press <Enter> to shutdown NOW");
new Scanner(System.in).nextLine();
executor.shutdownNow();
}
Что вы подразумеваете под снаружи?