Как прервать потоки ExecutorService - PullRequest
27 голосов
/ 14 февраля 2012

При использовании ExecutorService, возвращаемого Executors.newSingleThreadExecutor(), как мне его прервать?

Ответы [ 3 ]

36 голосов
/ 14 февраля 2012

Чтобы сделать это, вам нужно submit() выполнить задачу на ExecutorService, а не вызывать execute(). Когда вы делаете это, возвращается Future, который можно использовать для управления запланированной задачей. В частности, вы можете вызвать cancel(true) для связанного Future, чтобы прервать задачу, которая выполняется в данный момент (или вообще пропустить выполнение, если задача еще не запущена).

Кстати, объект, возвращаемый Executors.newSingleThreadExecutor(), на самом деле ExecutorService.

5 голосов
/ 06 мая 2015

Еще один способ прервать внутренне управляемые потоки исполнителя - это вызвать метод shutdownNow(..) на ExecutorService. Однако обратите внимание, что в отличие от решения @ erickson, это приведет к тому, что весь ThreadPoolExecutor станет непригодным для дальнейшего использования.

Я считаю этот подход особенно полезным в тех случаях, когда ExecutorService больше не нужен, и в других случаях нет необходимости хранить вкладки на экземплярах Future (ярким примером этого является метод exit(..) вашего приложения).

Соответствующая информация из ExecutorService#shutdownNow(..) javadocs:

Пытается остановить все активно выполняемые задачи, останавливает обработку ожидающих заданий и возвращает список ожидающих заданий выполнение.

Нет никаких гарантий, кроме попыток изо всех сил остановить обработку активно выполняющие задачи. Например, типичные реализации будут отменить через Thread.interrupt, поэтому любая задача, которая не отвечает на прерывания никогда не прекращаются.

0 голосов
/ 15 июня 2018

Одним из правильных способов может быть настройка / внедрение ThreadFactory для executorservice, и из фабрики потоков вы получите дескриптор созданного потока, а затем вы можете запланировать некоторую задачу для прерывания интересующего потока.

Демонстрационная часть кода для переписанного метода "newThread" в ThreadFactory:

ThreadFactory customThreadfactory new ThreadFactory() {

            public Thread newThread(Runnable runnable) {
                final Thread thread = new Thread(runnable);
                if (namePrefix != null) {
                    thread.setName(namePrefix + "-" + count.getAndIncrement());
                }
                if (daemon != null) {
                    thread.setDaemon(daemon);
                }
                if (priority != null) {
                    thread.setPriority(priority);
                }

                scheduledExecutorService.schedule(new Callable<String>() {
                    public String call() throws Exception {
                        System.out.println("Executed!");
                        thread.interrupt();
                        return "Called!";

                    }
                },
                5,
                TimeUnit.SECONDS);

                return thread;
            }
        }

Затем вы можете использовать ниже для создания вашего экземпляра executorservice:

ExecutorService executorService = Executors.newFixedThreadPool(3,
        customThreadfactory);

Затем через 5 секунд прерываниесигнал будет отправлен потокам в executorservice.

...