Служба Java Executor запускает потоки при запуске приложения - PullRequest
0 голосов
/ 17 октября 2018

Когда мое приложение запускается, создается объект службы executor (использующий Executors.newFixedThreadPool (maxThreadNum) в java.util.concurrent).Когда приходят запросы, служба executor создает потоки для их обработки.

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

Я сделал следующее:

executorService = Executors.newFixedThreadPool(200);
for (int i=0; i<200; i++) {
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println("Start thread in pool " );
        }
    });
}

Он создаст 200 потоков в пуле executorService при запуске приложения.

Интересно, этоправильный способ создания потоков при запуске приложения?Или есть лучший способ сделать это?

Ответы [ 5 ]

0 голосов
/ 17 октября 2018

Если вы можете использовать ThreadPoolExecutor напрямую, а не ExecutorService из Executors 1 , то, возможно, существует более стандартный / поддерживаемый способ запуска всего ядрапотоки немедленно.

int nThreads = 200;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 
        0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
executor.prestartAllCoreThreads();

Выше используется prestartAllCoreThreads().

Обратите внимание, что в настоящее время реализация Executors.newFixedThreadPool(int) создает ThreadPoolExecutor в точномтак же, как указано выше.Это означает, что вы можете технически привести ExecutorService, возвращенный фабричным методом, к ThreadPoolExecutor.В документации нет ничего, что гарантирует , однако это будет ThreadPoolExecutor.


1.ThreadPoolExecutor реализует ExecutorService, но предоставляет больше функциональности.Кроме того, многие из фабричных методов в Executors либо возвращают ThreadPoolExecutor напрямую, либо обертку, которая делегируется одному.Некоторые, например newWorkStealingPool, используют ForkJoinPool.Опять же, возвращаемые типы этих фабричных методов являются деталями реализации, поэтому не слишком полагайтесь на них.

0 голосов
/ 17 октября 2018

Интересно, это правильный способ создания потоков при запуске приложения?

Да.Это правильный способ создания потоков.

Или есть лучший способ сделать это?

Может быть.При некоторых рабочих нагрузках вы можете использовать пул потоков с переменным числом потоков (в отличие от созданного newFixedThreadPool) - тот, который удаляет из потоков пула, которые простаивали в течение некоторого времени.

0 голосов
/ 17 октября 2018

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

Однако обратите внимание, что ThreadPool через некоторое время вернет свободные потоки.Это может вас укусить, если вы не обращаете на это внимания.

0 голосов
/ 17 октября 2018

Вам не хватает shutdown(). Очень важно отключить службу Executor после завершения операции.Так что try,catch and Finally block

try{ executorService.execute(...); }catach(Exception e){ ... }finally{ executorService.shutdown(); //Mandatory }

0 голосов
/ 17 октября 2018

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

Отличный способ узнать, сколько у вас процессорных ядер:

int cores = Runtime.getRuntime().availableProcessors();

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

Но, в конце концов, ваш код в полном порядке.

...