java что такое executor

Executor Framework в Java

Java всегда сильно поддерживает параллельное и многопоточное программирование. Но в начале, до Java 5, поддержка была в форме вызова собственных конструкций на уровне приложений. Это было недостатком, потому что вы не могли обрабатывать примитивные вызовы более эффективно.

Что такое Executor Framework в Java?

Платформа Executor Framework в Java содержит множество компонентов, которые используются для эффективного управления несколькими потоками. Была выпущена с JDK 5, который используется для запуска объектов Runnable без создания новых потоков каждый раз, а также в основном с повторным использованием уже созданных потоков.

API-интерфейс Executor отделяет выполнение задачи от фактической задачи, выполняемой с помощью исполнителя. Это сосредоточено вокруг интерфейса Executor и его подчиненного интерфейса ExecutorService и класса ThreadPoolExecutor.

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

Пример

В этом примере класс Test реализует Runnable и параметризируется для ввода строки. Также объявлено, чтобы бросить исключение. Кроме того, обратите внимание, что эта способность выдавать исключение исполнителю и исполнителю, возвращающему это исключение обратно, имеет большое значение, поскольку помогает ему узнать состояние выполнения задачи.

Есть в основном 4 типа Executor.

SingleThreadExecutor

Имеет только один поток и используется для последовательного выполнения задач. Если какой-либо поток умирает из-за исключения во время выполнения задачи, создается новый поток для замены старого потока, а последующие задачи выполняются в новом потоке.

FixedPoolExecutor

CachedThreadExecutor

В основном используется, когда на линии много коротких параллельных задач, ожидающих выполнения. При сравнении с фиксированным пулом потоков количество потоков в этом пуле исполнителей здесь не ограничено. Если все потоки заняты выполнением назначенных задач и когда появляется новая задача, он создаст и добавит новый поток к исполнителю. Если поток остается бездействующим в течение почти шестидесяти секунд, он прекращается и удаляется из кэша.

ScheduledExecutor

Используется, когда у вас есть задача, которую нужно запускать через регулярные промежутки времени, или если вы хотите отложить определенную задачу. Задачи могут быть запланированы в ScheduledExecutor с использованием любого из двух методов scheduleAtFixedRate или scheduleWithFixedDelay.

Источник

Собеседование по Java — многопоточность (вопросы и ответы)

Вопросы и ответы для собеседования Java по теме — многопоточность.

К списку вопросов по всем темам

Вопросы

1. Дайте определение понятию “процесс”.
2. Дайте определение понятию “поток”.
3. Дайте определение понятию “синхронизация потоков”.
4. Как взаимодействуют программы, процессы и потоки?
5. В каких случаях целесообразно создавать несколько потоков?
6. Что может произойти если два потока будут выполнять один и тот же код в программе?
7. Что вы знаете о главном потоке программы?
8. Какие есть способы создания и запуска потоков?
9. Какой метод запускает поток на выполнение?
10. Какой метод описывает действие потока во время выполнения?
11. Когда поток завершает свое выполнение?
12. Как синхронизировать метод?
13. Как принудительно остановить поток?
14. Дайте определение понятию “поток-демон”.
15. Как создать поток-демон?
16. Как получить текущий поток?
17. Дайте определение понятию “монитор”.
18. Как приостановить выполнение потока?
19. В каких состояниях может пребывать поток?
20. Что является монитором при вызове нестатического и статического метода?
21. Что является монитором при выполнении участка кода метода?
22. Какие методы позволяют синхронизировать выполнение потоков?
23. Какой метод переводит поток в режим ожидания?
24. Какова функциональность методов notify и notifyAll?
25. Что позволяет сделать метод join?
26. Каковы условия вызова метода wait/notify?
27. Дайте определение понятию “взаимная блокировка”.
28. Чем отличаются методы interrupt, interrupted, isInterrupted?
29. В каком случае будет выброшено исключение InterruptedException, какие методы могут его выбросить?
30. Модификаторы volatile и метод yield().
31. Пакет java.util.concurrent
32. Есть некоторый метод, который исполняет операцию i++. Переменная i типа int. Предполагается, что код будет исполнятся в многопоточной среде. Следует ли синхронизировать блок?
33. Что используется в качестве mutex, если метод объявлен static synchronized? Можно ли создавать новые экземпляры класса, пока выполняется static synchronized метод?
34. Предположим в методе run возник RuntimeException, который не был пойман. Что случится с потоком? Есть ли способ узнать о том, что Exception произошел (не заключая все тело run в блок try-catch)? Есть ли способ восстановить работу потока после того как это произошло?
35. Какие стандартные инструменты Java вы бы использовали для реализации пула потоков?
36.Что такое ThreadGroup и зачем он нужен?
37.Что такое ThreadPool и зачем он нужен?
38.Что такое ThreadPoolExecutor и зачем он нужен?
39.Что такое «атомарные типы» в Java?
40.Зачем нужен класс ThreadLocal?
41.Что такое Executor?
42.Что такое ExecutorService?
43.Зачем нужен ScheduledExecutorService?

Ответы

1. Дайте определение понятию “процесс”.

Процесс — это совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированы друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие между процессами осуществляется с помощью специальных средств). Для каждого процесса ОС создает так называемое «виртуальное адресное пространство», к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система же отвечает за то, как виртуальное пространство процесса проецируется на физическую память.

Многопоточность в Java: http://habrahabr.ru/post/164487/

2. Дайте определение понятию “поток”.

Один поток («нить» или «трэд») – это одна единица исполнения кода. Каждый поток последовательно выполняет инструкции процесса, которому он принадлежит, параллельно с другими потоками этого процесса.

Thinking in Java.Параллельное выполнение. http://wikijava.it-cache.net/index.php@title=Glava_17_Thinking_in_Java_4th_edition.html

3. Дайте определение понятию “синхронизация потоков”.

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

Java поддерживает несколько потоков для выполнения. Это может привести к тому, что два или более потока получат доступ к одному и тому же полю или объекту. Синхронизация — это процесс, который позволяет выполнять все параллельные потоки в программе синхронно. Синхронизация позволяет избежать ошибок согласованности памяти, вызванных непоследовательным доступом к общей памяти.
Когда метод объявлен как синхронизированный — нить держит монитор для объекта, метод которого исполняется. Если другой поток выполняет синхронизированный метод, ваш поток заблокируется до тех пор, пока другой поток не отпустит монитор.
Синхронизация достигается в Java использованием зарезервированного слова synchronized. Вы можете использовать его в своих классах определяя синхронизированные методы или блоки. Вы не сможете использовать synchronized в переменных или атрибутах в определении класса.

Синхронизация потоков, блокировка объекта и блокировка класса info.javarush.ru: http://goo.gl/gW4ONp

4. Как взаимодействуют программы, процессы и потоки?

Чаще всего одна программа состоит из одного процесса, но бывают и исключения (например, браузер Chrome создает отдельный процесс для каждой вкладки, что дает ему некоторые преимущества, вроде независимости вкладок друг от друга). В каждом процессе может быть создано множество потоков. Процессы разделены между собой (>программы), потоки в одном процессе могут взаимодействовать друг с другом (методы wait, notify, join и т.д.).

5. В каких случаях целесообразно создавать несколько потоков?

Многопоточные приложения применяются в случаях, когда можно разделить программу на несколько относительно независимых частей. В этом случае чтобы один код не ждал другой их помещают в различные потоки. В качестве примера можно привести программу с графическим интерфейсом — пока выполняются какие-либо длительные вычисления в одном потоке, интерфейс может быть доступен пользователю и не зависать, если он выполняется в другом потоке.

6. Что может произойти если два потока будут выполнять один и тот же код в программе?

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

7. Что вы знаете о главном потоке программы?

Маленькие программы на Java обычно состоят из одной нити, называемой «главной нитью» (main thread). Но программы побольше часто запускают дополнительные нити, их еще называют «дочерними нитями». Главная нить выполняет метод main и завершается. Аналогом такого метода main, для дочерних нитей служит метод run интерфейса Runnable. Много потоков — много методов main (run()).

8. Какие есть способы создания и запуска потоков?

Существует несколько способов создания и запуска потоков.

С помощью класса, реализующего Runnable

С помощью класса, расширяющего Thread

С помощью класса, реализующего java.util.concurrent.Callable

Источник

Фреймворк Executor в Java

java что такое executor. Смотреть фото java что такое executor. Смотреть картинку java что такое executor. Картинка про java что такое executor. Фото java что такое executor

Sep 15, 2020 · 6 min read

java что такое executor. Смотреть фото java что такое executor. Смотреть картинку java что такое executor. Картинка про java что такое executor. Фото java что такое executor

Вплоть до Java 5 создавать потоки и управлять ими было возможно только на уровне приложения. Объекты Thread требуют значительного объема памяти. Таким образом, если постоянно создавать много таких объектов в крупномасштабном приложении, это приведет к существенным затратам памяти. Поэтому создание потоков и управление ими лучше отделить от остальной части приложения.

В качестве решения Java предоставляет фреймворк Executor. Он содержит множество функций для эффективного управления несколькими потоками. Не нужно каждый раз создавать новые потоки с помощью Executor — он позволяет использовать уже созданные потоки, когда вам это необходимо. В результате экономится как память вашего Java-приложения, так и ваше драгоценное время.

И з этой статьи вы узнаете о фреймворке Executor, пуле потоков и различных методах их создания, а также о том, как с их помощью управлять потоками. Давайте начнем.

Интерфейсы и классы Executor

Пулы потоков

newSingleThreadExecutor()

newFixedThreadPool()

newCachedThreadPool()

Когда мы создаем пул потоков с помощью этого метода, максимальный размер пула потоков устанавливается на максимальное целочисленное значение в Java. Этот метод создает новые потоки по запросу и разрушает потоки, которые простаивают больше минуты, если запрос отсутствует.

newScheduledThreadPool()

Как видно из примера:

Каждый из этих методов полезен в своём определённом сценариев.

Вот и всё о пулах потоков. Теперь — некоторые важные замечания насчет того, как использовать фреймворк Executor.

Важные замечания

На этом всё. Надеюсь, пулы потоков и Java ExecutorService стали для вас понятнее. Спасибо за чтение и счастливого кодирования!

Источник

Многопоточное программирование в Java 8. Часть первая. Параллельное выполнение кода с помощью потоков

Авторизуйтесь

Многопоточное программирование в Java 8. Часть первая. Параллельное выполнение кода с помощью потоков

java что такое executor. Смотреть фото java что такое executor. Смотреть картинку java что такое executor. Картинка про java что такое executor. Фото java что такое executor

Добро пожаловать в первую часть руководства по параллельному программированию в Java 8. В этой части мы на простых примерах рассмотрим, как выполнять код параллельно с помощью потоков, задач и сервисов исполнителей.

Впервые Concurrency API был представлен вместе с выходом Java 5 и с тех пор постоянно развивался с каждой новой версией Java. Большую часть примеров можно реализовать на более старых версиях, однако в этой статье я собираюсь использовать лямбда-выражения. Если вы все еще не знакомы с нововведениями Java 8, рекомендую посмотреть мое руководство.

Потоки и задачи

Все современные операционные системы поддерживают параллельное выполнение кода с помощью процессов и потоков. Процесс — это экземпляр программы, который запускается независимо от остальных. Например, когда вы запускаете программу на Java, ОС создает новый процесс, который работает параллельно другим. Внутри процессов мы можем использовать потоки, тем самым выжав из процессора максимум возможностей.

Поскольку интерфейс Runnable функциональный, мы можем использовать лямбда-выражения, которые появились в Java 8. В примере мы создаем задачу, которая выводит имя текущего потока на консоль, и запускаем ее сначала в главном потоке, а затем — в отдельном.

Результат выполнения этого кода может выглядеть так:

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

Потоки могут быть приостановлены на некоторое время. Это весьма полезно, если мы хотим сэмулировать долго выполняющуюся задачу. Например, так:

Работать с потоками напрямую неудобно и чревато ошибками. Поэтому в 2004 году в Java 5 добавили Concurrency API. Он находится в пакете java.util.concurrent и содержит большое количество полезных классов и методов для многопоточного программирования. С тех пор Concurrency API непрерывно развивался и развивается.

Давайте теперь подробнее рассмотрим одну из самых важных частей Concurrency API — сервис исполнителей (executor services).

Исполнители

Concurrency API вводит понятие сервиса-исполнителя (ExecutorService) — высокоуровневую замену работе с потоками напрямую. Исполнители выполняют задачи асинхронно и обычно используют пул потоков, так что нам не надо создавать их вручную. Все потоки из пула будут использованы повторно после выполнения задачи, а значит, мы можем создать в приложении столько задач, сколько хотим, используя один исполнитель.

Вот как будет выглядеть наш первый пример с использованием исполнителя:

Класс Executors предоставляет удобные методы-фабрики для создания различных сервисов исполнителей. В данном случае мы использовали исполнитель с одним потоком.

Вот как я предпочитаю останавливать исполнителей:

Исполнитель пытается завершить работу, ожидая завершения запущенных задач в течение определенного времени (5 секунд). По истечении этого времени он останавливается, прерывая все незавершенные задачи.

Callable и Future

Давайте напишем задачу, которая возвращает целое число после секундной паузы:

Callable-задачи также могут быть переданы исполнителям. Но как тогда получить результат, который они возвращают? Поскольку метод submit() не ждет завершения задачи, исполнитель не может вернуть результат задачи напрямую. Вместо этого исполнитель возвращает специальный объект Future, у которого мы сможем запросить результат задачи.

Задачи жестко связаны с сервисом исполнителей, и, если вы его остановите, попытка получить результат задачи выбросит исключение:

Таймауты

Любой вызов метода future.get() блокирует поток до тех пор, пока задача не будет завершена. В наихудшем случае выполнение задачи не завершится никогда, блокируя ваше приложение. Избежать этого можно, передав таймаут:

Выполнение этого кода вызовет TimeoutException :

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

InvokeAll

InvokeAny

Используем этот метод, чтобы создать несколько задач с разными строками и задержками от одной до трех секунд. Отправка этих задач исполнителю через метод invokeAny() вернет результат задачи с наименьшей задержкой. В данном случае это «task2»:

ForkJoinPool впервые появился в Java 7, и мы рассмотрим его подробнее в следующих частях нашего руководства. А теперь давайте посмотрим на исполнители с планировщиком (scheduled executors).

Исполнители с планировщиком

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

ScheduledExecutorService способен запускать задачи один или несколько раз с заданным интервалом.

Этот пример показывает, как заставить исполнитель выполнить задачу через три секунды:

Кроме того, он принимает начальную задержку, которая определяет время до первого запуска.

Обратите внимание, что метод scheduleAtFixedRate() не берет в расчет время выполнения задачи. Так, если вы поставите задачу, которая выполняется две секунды, с интервалом в одну, пул потоков рано или поздно переполнится.

В этом примере мы ставим задачу с задержкой в одну секунду между окончанием выполнения задачи и началом следующей. Начальной задержки нет, и каждая задача выполняется две секунды. Так, задачи будут запускаться на 0, 3, 6, 9 и т. д. секунде. Как видите, метод scheduleWithFixedDelay() весьма полезен, если мы не можем заранее сказать, сколько будет выполняться задача.

Это была первая часть серии статей про многопоточное программирование. Настоятельно рекомендую разобрать вышеприведенные примеры самостоятельно. Все они доступны на GitHub. Можете смело форкать репозиторий и добавлять его в избранное.

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

Источник

ExecutorService в Java

Язык программирования Java очень эффективно работает с многопоточными приложениями, которые требуют, чтобы задачи выполнялись одновременно в потоке. Любому приложению становится сложно одновременно выполнять большое количество потоков. Итак, чтобы преодолеть эту проблему, Java поставляется с ExecutorService, который является подчиненным интерфейсом платформы Executors.

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

Исполнитель – это фреймворк, который помогает вам создавать потоки в приложении и управлять ими. Фреймворк исполнителя поможет вам в следующих задачах.

java что такое executor. Смотреть фото java что такое executor. Смотреть картинку java что такое executor. Картинка про java что такое executor. Фото java что такое executor

Пример

Это субинтерфейс структуры исполнителя, который добавляет определенные функции для управления жизненным циклом потока приложения. Он также предоставляет метод submit(), который может принимать как запускаемые, так и вызываемые объекты.

В следующем примере мы создадим ExecutorService с одним потоком, а затем отправим задачу для выполнения внутри потока.

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

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

Реализации

ExecutorService очень похож на пул потоков. Фактически, реализация ExecutorService в пакете java.util.concurrent является реализацией пула потоков. ExecutorService имеет следующие реализации в пакете java.util.concurrent:

ThreadPoolExecutor

ThreadPoolExecutor выполняет указанные задачи, используя один из своих внутренних потоков пула.
java что такое executor. Смотреть фото java что такое executor. Смотреть картинку java что такое executor. Картинка про java что такое executor. Фото java что такое executor
Создание threadPoolExecutor

ScheduledThreadPoolExecutor

Java.util.concurrent.ScheduledThreadPoolExecutor – это ExecutorService, который может планировать выполнение задач после задержки или повторное выполнение с фиксированным интервалом времени между каждым выполнением.

Использование

Есть несколько разных способов делегировать задачи ExecutorService.

execute(Runnable)

Выполнение ExecutorService execute(Runnable) принимает объект java.lang.Runnable и выполняет его асинхронно.

Невозможно получить результат выполнения Runnable, для этого вам нужно использовать Callable.

submit(Runnable)

Метод Java ExecutorService submit(Runnable) принимает реализацию Runnable и возвращает будущий объект. Будущий объект можно использовать для проверки завершения выполнения Runnable.

submit(Callable)

Метод submit(Callable) Java ExecutorService аналогичен submit(Runnable), но для него используется Java Callable вместо Runnable.

invokeAny()

Метод invokeAny() принимает коллекцию вызываемых объектов. Вызов этого метода не возвращает будущего, но возвращает результат одного из вызываемых объектов.

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

InvokeAll()

Метод invokeAll() вызывает все вызываемые объекты, переданные в качестве параметров. Он возвращает будущие объекты, которые можно использовать для получения результатов выполнения каждого вызываемого объекта.

Runnable vs Callable

Запускаемый и вызываемый интерфейсы очень похожи друг на друга. Разница видна в объявлении интерфейсов. Оба интерфейса представляют собой задачу, которая может выполняться одновременно потоком или ExecutorService.

Основное различие между ними заключается в том, что метод call() может возвращать объект из вызова метода. И метод call() может вызвать исключение, а метод run() – нет.

Как отменить задачу?

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

Завершение

Чтобы потоки не запускались даже после завершения выполнения, следует закрыть ExecutorService. Чтобы завершить потоки внутри ExecutorService, вы можете вызвать метод shutdown().

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *