Освобожден ли поток, использованный в аннотации @Scheduled, в пул до завершения выполнения? - PullRequest
2 голосов
/ 27 марта 2019

У меня есть 5 @Scheduled аннотированных методов и размер пула моего ThreadPoolTaskScheduler равен 10. Аннотации моих методов такие же и такие.

@ Запланировано (fixedDelay = 1000, initialDelay = 10000)

Мой вопрос таков;

Когда один из запланированных методов получает поток из пула и начинает работать; освобождает ли поток для пула до его выполнения? (например, в случае переключения контекста и т. д.) или этот поток используется до конца выполнения?

Я имею в виду, возможно ли, чтобы какая-то часть запланированного задания выполнялась с потоком-1, а какая-то часть с потоком-2?

1 Ответ

2 голосов
/ 27 марта 2019

Потоки сложны, и мое понимание не так велико, как у других, но вот моя попытка краткого объяснения того, как работает аннотация @Scheduled Spring:

Spring использует TaskScheduler:

public interface TaskScheduler {

    ScheduledFuture schedule(Runnable task, Trigger trigger);

    ScheduledFuture schedule(Runnable task, Date startTime);

    ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);

    ScheduledFuture scheduleAtFixedRate(Runnable task, long period);

    ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);

    ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);

}

https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html#scheduling-task-scheduler

Который представляет аннотированный код, то есть код задачи, высокоуровневому объекту параллелизма, называемому исполнителем.Класс исполнителя - ThreadPoolTaskExecutor.Этот класс отправляет задачи в пул потоков для запуска первым доступным потоком в пуле.Заданный вами размер пула потоков определяет, сколько активных потоков вы можете иметь.Если вы установите для allowCoreThreadTimeOut значение true, то потоки в пуле, у которых нет работы, доступной для выполнения в течение их интервала времени ожидания, будут прерваны.

Spring использует ThreadPoolTaskExecutor для управления пулом потоков:

https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.java

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

В конечном итоге класс java.lang.Thread запускает экземпляры Runnable или Callable, которые создаются ThreadPoolTaskExecutor.Класс Thread реализует метод run(), который, по сути, является вашим кодом, для которого поток должен выполняться:

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc) {
...

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/lang/Thread.java

Фактическое переключение между потоками, т.е. контекстПереключатель зависит от ОС , но в общем случае потоки будут разделены между ЦП, а затем каждый ЦП циклически перебирает потоки на основе интервала времени ожидания и выполняет небольшую работу, а затем приостанавливает и непрерывно переключается между потоками до выполнения задачи.выполнено.

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

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

Вот дополнительная информация из документации Oracle , которая объясняет пулы потоков:

Большинствореализации executor в java.util.concurrent используют пулы потоков, которые состоят из рабочих потоков.Этот тип потока существует отдельно от задач Runnable и Callable, которые он выполняет, и часто используется для выполнения нескольких задач.

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

Одним из распространенных типов пула потоков является фиксированный пул потоков.Этот тип пула всегда имеет указанное количество запущенных потоков;если поток каким-либо образом завершен, пока он еще используется, он автоматически заменяется новым потоком.Задачи передаются в пул через внутреннюю очередь, в которой хранятся дополнительные задачи, когда есть более активные задачи, чем потоки.

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

...