Java: принудительная остановка потоков ExecutorService - PullRequest
5 голосов
/ 10 мая 2011

Мой код:


String[] torrentFiles = new File("/root/torrents/").list();

        if(torrentFiles.length == 0 || torrentFiles == null)
        {
            System.exit(0);
        }

        ex = Executors.newFixedThreadPool(3);

        for(String torrentFile : torrentFiles)
        {
            ex.submit(new DownloadTorrent("/root/torrents/" + torrentFile));
        }

        ex.shutdown();

        try
        {
            ex.awaitTermination(30, TimeUnit.MINUTES);
        }
        catch(InterruptedException ex1)
        {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex1);
        }

Но иногда загрузка торрента принимает неизвестное значение времени, и «awaitTermination» не работает так, как я хочу. Мне нужно остановить все выполненные потоки немедленно через полчаса, но, как я знаю, «awaitTermination» использует только метод interrupt(), который работает только в циклах или в ожидании. Так что тайм-аут не работает, если этот момент случается. Итак, как?

Ответы [ 6 ]

8 голосов
/ 10 мая 2011

Мгновенное завершение потока никогда не гарантируется, если поток периодически не проверяет наличие флага isInterrupted () (или ожидает прерывистый метод, то есть который генерирует InterruptedException).

Рассмотрите возможность реализации ваших рабочих потоков таким образом, когда они периодически проверяют isInterrupted (). Это может быть что-то вроде этого:

public void run() { 
  byte[] data;
  do {
     data = receiveDataChunk(timeout);
     processData(data);
  } while(!isInterrupted() && data != null);
}
6 голосов
/ 10 мая 2011

Поскольку загрузка торрента, вероятно, связана с блокировкой операций ввода-вывода, простого вызова cancel() / shutdownNow() будет недостаточно, поскольку блокирование операций ввода-вывода не гарантированно завершается при прерывании их соответствующих потоков.

Вам также необходимо закрыть базовые сокеты, чтобы отменить блокировку ввода-вывода, см. Как немедленно прекратить блокировку потока при операции ввода-вывода сокета? .

6 голосов
/ 10 мая 2011

ExecutorService.shutdownNow() попытается остановить все выполняющиеся потоки ..

Вот цитата из javadoc

List<Runnable> shutdownNow()

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

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

1 голос
/ 10 мая 2011

ExecutorService.submit(...) возвращает Future<?> с методом cancel(). Вы должны следить за тем, что они могут вызывать, когда вы хотите, чтобы каждая задача остановилась.

0 голосов
/ 05 сентября 2017

Am Используя этот код, который я создал.

Он генерирует много PDF-файлов из множества HTML-шаблонов, используя wkhtmltopdf .

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

About getListOfCallables возвращает правильное оптимальное пороговое значение для числа потоков для использования при создании фиксированного пула.

Так что я не могу справиться с тем, что вокруг него лежит множество мертвых потоков, и мой процессор EC2 застрял на 100%.

Я использовал:

  • shutdown ()
  • shutdownNow () в ожидании
  • shutdownNow () в исключительной части

Список fileGenerationHtmlToPdfList = getListOfCallables (пути, имя, параметры);

            ExecutorService executorService = Executors.newFixedThreadPool(fileGenerationHtmlToPdfList.size());


            List<Future<ArrayList<File>>> futures = null;

            try {
                futures = executorService.invokeAll(fileGenerationHtmlToPdfList);
                try {
                    for(Future f: futures) {
                        files.addAll((ArrayList<File>)f.get());
                    }

                } catch (InterruptedException ex) {
                    Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
                } catch (ExecutionException ex) {
                    Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
            }

 executorService.shutdown();//try shutdown

            try {
                if (executorService.awaitTermination(5, TimeUnit.SECONDS)) {
                    Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Done ShutDowned");
                } else {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException ex) {
                executorService.shutdownNow();
                Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
            }
0 голосов
/ 19 января 2013

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

boolean isTerminated = mPoolThreads.isTerminated();
while (!isTerminated) {
    mPoolThreads.shutdownNow();
    isTerminated = mPoolThreads.isTerminated();
    Log.i(Constants.LOG_TAG, "Stop threads: the threads are not terminated yet");
}
Log.w(Constants.LOG_TAG, "Stop threads: Terminated");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...