У меня есть вопрос о пулах потоков исполнителей, работающих один внутри другого.
Допустим, у меня есть служба Spring с запланированным методом, а другая служба создает ExecutorService и запускает некоторый метод действия.
@Service
public class ScheduledService
{
@Autowired
WorkService workService;
@Scheduled(cron = "1 * * * * * ")
public void method() {
workService.execute();
}
}
@Service
public class WorkService {
private ExecutorService executorService = Executors.newFixedThreadPool(20);
public void execute() {
executorService.submit(()->action());
}
private void action() {
//some action
}
}
Насколько я знаю, по умолчанию размер пула для @Scheduled равен 1. Внутри потока из этого пула я пытаюсь создать новый executorService с большим пулом.
Итак, вопрос в том, как выполнение будет распределяться по ядрам ЦП, действительно ли служба исполнителя будет работать параллельно? У меня ощущение, что нет. Я попытался запустить одно и то же задание на машине с 2 и 4 виртуальными ядрами, и время выполнения было одинаковым.
Спасибо.




То, как он распределяется по ядрам ЦП, зависит также от того, насколько загружена операционная система, но, скажем, больше ничего не происходит, каждое ядро ЦП может выполнять один поток. Если активных потоков больше, чем ядер ЦП, операционная система отвечает за распределение времени ЦП между потоками.
В вашем примере один поток выполнит метод @Scheduled, который довольно быстр, потому что он мало что делает, просто отправляет новое действие в службу-исполнитель.
Затем служба-исполнитель, имеющая до 20 потоков, выполнит действие в первом доступном потоке из 20.
Так что да, действия будут выполняться параллельно.
Вы можете попробовать очень часто планировать свой метод, скажем, каждую секунду:
@Scheduled(cron = "* * * ? * *")
Затем сделайте что-то дольше 1 секунды в своем действии (иначе действие завершится до следующего расписания). Вы увидите действия, выполняющие работу параллельно.
Кстати, почему бы не использовать ScheduledExecutorService? Или настроить Spring для использования нескольких потоков?
Спасибо! Да, я добавил журнал для распечатки имен потоков, он работает параллельно. Насчет ScheduledExecutorService — в реальном коде логика сложнее. Запланирована служба опроса очереди на наличие новых сообщений, если она получает сообщение - она начинает обработку, и только в одной из частей обработки я могу делать вещи параллельно.