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

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

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

6 ответов


по данным параллелизм Java на практике:

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

если вы можете использовать ScheduledThreadExecutor вместо Timer, это сделать.

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


если это доступно для вас, то трудно придумать причину не для использования Java 5 executor framework. Зову:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

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

  • вы можете настроить его при необходимости (см. newScheduledThreadPoolExecutor() или ScheduledThreadPoolExecutor класс)
  • "one off" исполнения могут возвращать результаты

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

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

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

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

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


вот еще несколько хороших практик вокруг использования таймера:

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

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


моя причина иногда предпочитая таймер над исполнителями.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);

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


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

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

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

плюсы ExecutorService над Timer

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

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

    преимущества:

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

    b. Вы можете управлять обработкой задач ( Кража работы, ForkJoinPool, invokeAll) так далее.

    c. Вы можете следить за ходом и состоянием потоков

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