Таймер Java против ExecutorService?

У меня есть код, где я планирую задачу, используя java.util.timer, Я огляделся и увидел ExecutorService может сделать то же самое. Итак, этот вопрос здесь, вы использовали Таймер и ExecutorService для планирования задач, в чем преимущество одного использования над другим?

Также хотел проверить, использовал ли кто-нибудь Timer класс и столкнулся с любыми вопросами, которые ExecutorService решено для них.

7 ответов

Решение

В соответствии с параллелизмом Java на практике:

  • Timer может быть чувствительным к изменениям системных часов, ScheduledThreadPoolExecutor нет.
  • Timer имеет только один поток выполнения, поэтому долго выполняющаяся задача может задержать выполнение других задач. ScheduledThreadPoolExecutor можно настроить с любым количеством потоков. Кроме того, вы можете полностью контролировать созданные потоки, если хотите (предоставляя ThreadFactory).
  • Исключения во время выполнения TimerTask убить эту одну нить, таким образом делая Timer dead:-( ... т.е. запланированные задачи больше не будут выполняться. ScheduledThreadExecutor не только перехватывает исключения во время выполнения, но и позволяет вам обрабатывать их, если хотите (переопределяя afterExecute метод из ThreadPoolExecutor). Задача, вызвавшая исключение, будет отменена, но другие задачи продолжат выполняться.

Если вы можете использовать ScheduledThreadExecutor вместо Timer, Сделай так.

Еще одна вещь... пока ScheduledThreadExecutor недоступна в библиотеке Java 1.4, есть Backport of JSR 166 ( java.util.concurrent ) к Java 1.2, 1.3, 1.4, которая имеет ScheduledThreadExecutor учебный класс.

Если это доступно для вас, то трудно придумать причину, по которой не следует использовать среду исполнения Java 5. Вызов:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

даст вам ScheduledExecutorService с аналогичной функциональностью Timer (т.е. он будет однопоточным), но чей доступ может быть немного более масштабируемым (под капотом он использует параллельные структуры, а не полную синхронизацию, как с Timer учебный класс). Используя ScheduledExecutorService также дает вам такие преимущества, как:

  • Вы можете настроить его при необходимости (см. newScheduledThreadPoolExecutor() или ScheduledThreadPoolExecutor учебный класс)
  • "Одноразовые" казни могут вернуть результаты

О единственных причинах придерживаться Timer Я могу думать о:

  • Это доступно до Java 5
  • Подобный класс предусмотрен в J2ME, что может упростить перенос вашего приложения (но в этом случае не составит труда добавить общий уровень абстракции).

ExecutorService является более новым и общим. Таймер - это просто поток, который периодически запускает то, что вы запланировали для него.

ExecutorService может быть пулом потоков или даже распространяться на другие системы в кластере и выполнять такие вещи, как одноразовое пакетное выполнение и т. Д.

Просто посмотрите, что каждый предлагает решить.

Вот еще несколько полезных практик по использованию таймера:

http://tech.puredanger.com/2008/09/22/timer-rules/

В общем, я бы использовал Timer для быстрых и грязных вещей и Executor для более надежного использования.

Со страницы документации Oracle на ScheduledThreadPoolExecutor

ThreadPoolExecutor, который может дополнительно запланировать выполнение команд после заданной задержки или периодическое выполнение. Этот класс предпочтительнее, чем Timer, когда требуется несколько рабочих потоков или когда требуется дополнительная гибкость или возможности ThreadPoolExecutor (который расширяет этот класс).

ExecutorService/ThreadPoolExecutor или же ScheduledThreadPoolExecutor Это очевидный выбор, когда у вас есть несколько рабочих потоков.

Плюсы ExecutorService над Timer

  1. Timer не может использовать преимущества доступных процессорных ядер в отличие ExecutorService особенно с несколькими задачами с использованием ароматов ExecutorService как ForkJoinPool
  2. ExecutorService предоставляет совместный API, если вам нужна координация между несколькими задачами. Предположим, что вам нужно отправить N рабочих задач и дождаться завершения всех из них. Вы можете легко достичь этого с помощью invokeAll API. Если вы хотите добиться того же с несколькими Timer задачи, это было бы не просто.
  3. ThreadPoolExecutor предоставляет лучший API для управления жизненным циклом потока.

    Пулы потоков решают две разные проблемы: они обычно обеспечивают повышенную производительность при выполнении большого количества асинхронных задач из-за уменьшения накладных расходов на вызовы для каждой задачи, и они обеспечивают средства ограничения и управления ресурсами, в том числе потоками, используемыми при выполнении коллекции задачи. Каждый ThreadPoolExecutor также поддерживает некоторую базовую статистику, такую ​​как количество выполненных задач

    Несколько преимуществ:

    а. Вы можете создавать / управлять / контролировать жизненный цикл потоков и оптимизировать накладные расходы на создание потоков

    б. Вы можете контролировать обработку заданий ( Work Stealing, ForkJoinPool, invokeAll) и т. Д.

    с. Вы можете отслеживать прогресс и здоровье потоков

    д. Обеспечивает лучший механизм обработки исключений

Моя причина, по которой я иногда предпочитаю Timer, а не Executors.newSingleThreadScheduledExecutor(), заключается в том, что я получаю гораздо более чистый код, когда мне нужен таймер для выполнения в потоках демона.

сравнить

private final ThreadFactory threadFactory = new ThreadFactory() {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
};
private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory); 

с

private final Timer timer = new Timer(true);

Я делаю это, когда мне не нужна надежность службы executor.

У меня была проблема с таймером, и я заменил его на ScheduledExecutorService , чтобы исправить это.

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

Другие вопросы по тегам