SingleThreadExecutor VS простой поток - PullRequest
0 голосов
/ 28 апреля 2018

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

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(runnable);

И

Thread thread = new Thread(runnable);
thread.start();

Я спрашиваю здесь только об одной теме.

Ответы [ 3 ]

0 голосов
/ 28 апреля 2018

Это абстракция , и они всегда бывают "стоимостными":

  • некоторое (потенциальное) количество «штрафа за производительность»
  • уменьшенное количество "контроля" (в этом весь смысл - вам не нужно иметь дело с деталями низкого уровня, поэтому, если вам нужно, ...)

Основным отличием является то, что служба позволяет отправлять несколько задач, тогда как поток может выполнять ровно один Runnable. С другой стороны, вам нужно беспокоиться о таких вещах, как «закрытие» службы.

Эмпирическое правило: аспекты производительности должны быть близки к "игнорируемым". Из-за этого вы предпочитаете «более абстрактное» решение службы исполнителя. Потому что это позволяет вам отделить ваши проблемы от фактических потоков. И что еще более важно: если вы когда-либо решите использовать другой тип реализации для этой службы ... остальной код не должен заботиться об этом.

Короче говоря: абстракция стоит, но в этом случае вы обычно предпочитаете "более абстрактное" решение. Потому что, в конце концов, это уменьшает сложность вашего решения.

0 голосов
/ 28 апреля 2018

Executors # newSingleThreadExecutor () создает ThreadPoolExecutor объект под капотом,
см. код здесь: http://www.docjar.com/html/api/java/util/concurrent/Executors.java.html

  133       public static ExecutorService newSingleThreadExecutor() {
  134           return new FinalizableDelegatedExecutorService
  135               (new ThreadPoolExecutor(1, 1,
  136                                       0L, TimeUnit.MILLISECONDS,
  137                                       new LinkedBlockingQueue<Runnable>()));
  138       }

Документация ThreadPoolExecutor объясняет, в каких ситуациях он дает преимущества:

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

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

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

0 голосов
/ 28 апреля 2018

Если у вас есть только один Runnable для выполнения, то между ними нет большой разницы .

Использование простого потока может быть немного более эффективным, поскольку создание ExecutorService, такого как ThreadPoolExecutor, имеет что-то, кроме создания нового потока. Например, создание очереди блокировки, создание политики, хотя эти действия выполняются неявно.

И вы должны shutdown исполнителю после того, как этот runnable был выполнен. В противном случае единственный поток в этом пуле никогда не завершится.

...