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


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

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

6 232

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 также дает вам такие преимущества как:

  • вы можете настроить его в случае необходимости (см. 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 over Timer

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

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

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

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

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

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

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