Исполняются ли Java Executors в потоке демона?

У меня была короткая java-программа, которая создавала однопоточный запланированный исполнитель, и я планировал задачу.

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

scheduledExecutorService.schedule(cloudWatchReporter, accumulateForMillis, TimeUnit.MILLISECONDS);

До наступления запланированного времени мой основной поток завершился, и JVM закрылась. Я ожидал, что перед завершением работы он дождется завершения таймера и выполнения запланированной задачи. Это не то, что случилось. Если бы я добавил достаточно сна непосредственно перед тем, как мой основной поток завершился, моя задача затем была бы выполнена до завершения работы JVM.

Есть ли у исполнителей главный поток, который управляет таймером? Или эффект таймера достигается каким-то другим способом? Если под управлением какого-либо главного потока, это поток демона или поток, не являющийся демоном?

См. Javadoc defaultThreadFactory(): Возвращает фабрику потоков по умолчанию, используемую для создания новых потоков. Эта фабрика создает все новые потоки, используемые Executor в той же ThreadGroup. [...] Каждый новый поток создается как поток, не являющийся демоном. с приоритетом, меньшим из Thread.NORM_PRIORITY, и максимальным приоритетом, разрешенным в группе потоков. [...]

Sotirios Delimanolis 13.09.2018 19:37

@SotiriosDelimanolis Я не спрашивал, являются ли потоки в пуле демонами или недемонами. Я спросил, существует ли поток, который создает потоки для пула, и является ли этот поток демоном или не-демоном.

Joe 17.09.2018 19:39

Все потоки в реализации ScheduledExecutorService JDK извлекают задачи из главной «очереди». Нет никакого «управляющего» потока. Потоки создаются и запускаются по мере необходимости (и максимум до 1 в вашем случае) из потока, вызывающего любой из методов schedule.

Sotirios Delimanolis 17.09.2018 19:52

Как работает таймер?

Joe 17.09.2018 21:20

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

Sotirios Delimanolis 17.09.2018 21:41
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
5
938
1

Ответы 1

Этот простой полный пример противоречит тому, что вы утверждаете в своем вопросе:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

class Test {

    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.schedule(() -> System.out.println("hello"), 10, TimeUnit.SECONDS);
    }
}

Запустите его, и вы увидите, что не только сообщение печатается через 10 секунд, но и программа не выходит. Итак, ваш основной поток не просто закончился. Вы, наверное, звоните System.exit().

Я запустил предоставленный вами код. Это работает, как вы сказали. Но я не могу заставить эти две строки в основном методе работать одинаково при выполнении в рамках теста JUnit. Тест просто завершается до того, как будет напечатан текст «привет». Выполняется ли тестовый код JUnit иначе, чем из основного метода? Я не упоминал об этом раньше, но мой первоначальный вызов метода расписания происходит из теста JUnit.

Joe 17.09.2018 19:58

Скорее всего, исполнитель JUnit вызывает System.exit () сразу после выполнения всех тестов. Если вы хотите, чтобы запланированное задание выполнялось, вам необходимо заблокировать тест на достаточно длительный период.

JB Nizet 17.09.2018 20:10

Другие вопросы по теме