В Java 5 было добавлено много вещей для организации многопоточности и особенно касаемо организации параллельного доступа. В этой и последующих статьях мы пройдемся по некоторыми из них.
ExecutorService
До Java 5 для организации работы с несколькими потоками приходилось использовать сторонние имплеменации пулинга или писать свой. С появлением ExecutorService
такая необходимость отпала.ExecutorService
исполняет асинхронный код в одном или нескольких потоках. Создание инстанса ExecutorService’а делается либо вручную через конкретные имплементации (ScheduledThreadPoolExecutor
илиThreadPoolExecutor
), но проще будет использовать фабрики класса Executors
. Например, если надо создать пул с 2мя потоками, то делается это так:
ExecutorService service = Executors.newFixedThreadPool(2);
Если требуется использовать кэширующий пул потоков, который создает потоки по мере необходимости, но переиспользует неактивные потоки (и подчищает потоки, которые были неактивные некоторое время), то это задается следующим образом:
ExecutorService service = Executors.newCachedThreadPool();
Теперь небольшой пример. Допустим, надо запустить какой-нибудь код асинхронно 10 раз. Основываясь на вышесказанном, код будет выглядеть так:
ExecutorService service = Executors.newCachedThreadPool();
for(int i = 0; i < 10; i++) {
service.submit(new Runnable() {
public void run() {
// snip... piece of code
}
});
}
Метод submit
также возвращает объект Future
, который содержит информацию о статусе исполнения переданного Runnable
или Callable
(который может возвращать значение). Из него можно узнать выполнился ли переданный код успешно, или он еще выполняется. Вызов метода get
на объекте Future
возвратит значение, который возвращает Callable
(или null
, если используется Runnable
). Метод имеет 2 checked-исключения: InterruptedException
, который бросается, когда выполнение прервано через методinterrupt()
, или ExecutionException
если код в Runnable
или Callable
бросил RuntimeException
, что решает проблему поддержки исключений между потоками.
ScheduledExecutorService
Иногда требуется выполнение кода асихронно и периодически или требуется выполнить код через некоторое время, тогда на помощь приходит ScheduledExecutorService
. Он позволяет поставить код выполняться в одном или нескольких потоках и сконфигурировать интервал или время, на которое выполненение будет отложено. Интервалом может быть время между двумя последовательными запусками или время между окончанием одного выполнения и началом другого. Методы ScheduledExecutorService
возвращают ScheduledFuture
, который также содержит значение отсрочки для выполнения ScheduledFuture
.
Например, если требуется отложить выполнение на 5 секунд, потребуется следующий код:
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.schedule(new Runnable() { ... }, 5, TimeUnit.SECONDS);
Если требуется назначить выполнение каждую секунду:
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new Runnable() { ... }, 0, 1, TimeUnit.SECONDS);
И, наконец, если требуется назначить выполнение кода с промежутком 1 секунда между выполнениями:
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(new Runnable() { ... }, 0, 1, TimeUnit.SECONDS);
Взято звідси