Что такое ExecutorService?

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Честно говоря, вопрос этот не слишком новый. Со времени выхода Java 5 и пакета java.util.concurrent.* прошло более 13 лет, но мне, за всю мою десятилетнюю практику, так ни разу и не пришлось столкнуться с этим зверем. Тем не менее, мне этот вопрос несколько раз задавали на собеседованиях и пришлось знакомиться.

Первое естественно с чего я начал это — Хабр. Но, к сожалению, нашёл здесь только две статьи:

habrahabr.ru/post/260953
habrahabr.ru/post/116363

Первая, очевидно, для тех, кто понимает и имеет опыт работы с ExecutorService. Вторая в меня, к сожалению, не вошла. Вроде небольшая и «по делу», но перечитав несколько раз я так и не понял, что же такое ExecutorService и с чем его едят. Поэтому пришлось садиться за Eclipse, курить читать javadoc и разбираться.

Итак, давайте рассмотрим простой пример:

ExecutorService service = Executors.newFixedThreadPool(3);
service.execute(new Runnable() {
    public void run() {
        System.out.println("Another thread was executed");
    }
});

В данном примере мы создали сам обьект ExecutorService и вызвали на нём метод execute. Передав в него самую обычную имплементацию потока. Всё это можно было бы соорудить и старым дедовским способом, но так, согласитесь, гораздо проще и изящнее. Фактически, мы быстро ответвили от текущего потока другой, асинхронный, который может что-то там выполнить в фоне.
Сам объект ExecutorService мы создали с помощью фабрики. Её методы вполне очевидны, поэтому не будем особо мусолить. Вот некоторые из них:

ExecutorService service1 = Executors.newSingleThreadExecutor();
ExecutorService service2 = Executors.newFixedThreadPool(3);
ExecutorService service3 = Executors.newScheduledThreadPool(3);

Помимо метода execute, который вызывается по принципу «выстрелил и забыл», наш сервис ещё имеет метод submit. Отличие от первого лишь в том, что последний возвращает объект интерфейса Future. Это просто замечательная возможность контролировать состояние потока, который мы запустили в фоне. Делается примерно так:

Future future = service.submit(new Runnable() {
    public void run() {
        System.out.println("Another thread was executed");
    }
});
...
future.get();

Обратите внимание, что метод get насмерть блокирует текущий поток и будет ждать пока фоновый не завершится. Теперь не нужно всех этих неочевидных join-ов! Если же мы боимся что наш фоновый поток не завершится никогда, можем использовать get(long,TimeUnit).

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

Future future = service.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Another thread was executed");
        return "result";
    }
});
...
System.out.println("Result: " + future.get());

Ну вот вкратце и всё. Остались методы создания ExecutorService-а в фабрике (их там много), остались методы самого ExecutorService, вопросы об обработке ошибок в фоновых потоках, но это уже совсем другая история…

На завершение не забывайте делать:

servcie.shutdown();

Или не делать, в случае, что все фоновые потоки у вас будут демонами.
Источник: https://habr.com/ru/post/554608/


Интересные статьи

Интересные статьи

«Безошибочный признак любви к истине, — не принимать никакую гипотезу с большей уверенностью, чем позволяют доказательства, на которых она основана» Джон Локк. ...
В течение последних трёх лет Nvidia создавала графические чипы, в которых помимо обычных ядер, используемых для шейдеров, устанавливались дополнительные. Эти ядра, называемые тензор...
Есть статьи о недостатках Битрикса, которые написаны программистами. Недостатки, описанные в них рядовому пользователю безразличны, ведь он не собирается ничего программировать.
Каждый лишний элемент на сайте — это кнопка «Не купить», каждая непонятность или трудность, с которой сталкивается клиент — это крестик, закрывающий в браузере вкладку с вашим интернет-магазином.
Если Вы используете в своих проектах инфоблоки 2.0 и таблицы InnoDB, то есть шанс в один прекрасный момент столкнуться с ошибкой MySQL «SQL Error (1118): Row size too large. The maximum row si...