Внутренняя очередь исполнителя запланированного пула потоков java

Я хочу написать программу, которая запускается каждые 30 минут. Я использую Java-исполнитель запланированного пула потоков для обработки задач, которые я отправляю исполнителю.

Я смотрел, что говорят официальные документы https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html

и я столкнулся с дилеммой.

Допустим, я отправил 5 задач в очередь и определил 10 потоков в пуле потоков.

  1. Есть ли вероятность, что одно из заданий будет выполнено дважды?

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

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

Вы можете разместить свой код?

xingbin 31.10.2018 14:17

Я запускаю код, указанный в учебнике, который я читаю, это ссылка на ide ide.geeksforgeeks.org/tRn5ZzZbtT

Gandalf 31.10.2018 14:20

@ 孙兴斌 Кто заботится об удалении обработанных элементов из очереди блокировки? Программист или исполнитель threadpool?

Gandalf 31.10.2018 14:23

@Gandalf код из опубликованной вами ссылки не использует ScheduledExecutorService. Для фиксированного пула потоков каждая отправленная задача выполняется ровно один раз.

Illyes Istvan 31.10.2018 14:23

@IllyesIstvan А что будет с задачей после ее выполнения? Удалено исполнителем из очереди?

Gandalf 31.10.2018 14:24

@Gandalf в вашем примере: да. В запланированном исполнителе запланированные задачи выполняются с заданной скоростью, поэтому они будут выполняться несколько раз. Вы можете уточнить свой вопрос? Вы хотите использовать запланированный пул потоков?

Illyes Istvan 31.10.2018 14:25

Как говорили другие, ThreadPoolExecutor гарантирует, что каждая задача будет выполнена один раз. Я хочу написать программу, которая запускается каждые 30 минут. Кажется, ThreadPoolExecutor не может этого достичь, вы ищете ScheduledThreadPoolExecutor? docs.oracle.com/javase/7/docs/api/java/util/concurrent/…

xingbin 31.10.2018 14:26

@IllyesIstvan - это то, для чего создан исполнитель, и в документации я не могу найти эту часть, убедившись, что обработанная задача действительно удалена.

Gandalf 31.10.2018 14:26

@ 孙兴斌 Хорошо. есть ли документация, подтверждающая это: 1. Он выполняется только один раз 2. Задача удаляется после обработки ... простите мой скептицизм, это звучит слишком волшебно, мне нужны некоторые документальные доказательства.

Gandalf 31.10.2018 14:28
0
9
764
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Он будет выполнен только один раз, исполнитель удалит его автоматически.

Это явно не задокументировано, хотя док подразумевает это:

Executes the given task sometime in the future.

Executors.newFixedThreadPool() создает новый ThreadPoolExecutor, используя LinkedBlockingQueue.

Из Executors.newFixedThreadPool():

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

Когда задачи отправляются на выполнение, ThreadPoolExecutor добавляет их в эту очередь. Далее рабочие потоки будут брать задачи из этой очереди и выполнять их.

Из ThreadPoolExecutor.getTask():

private Runnable getTask() {
  // ...
        try {
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

Согласно контракту BlockingQueue.take(), извлечение элемента из очереди также подразумевает его удаление.

/**
 * Retrieves and removes the head of this queue, waiting if necessary
 * until an element becomes available.
 *
 * @return the head of this queue
 * @throws InterruptedException if interrupted while waiting
 */
E take() throws InterruptedException;

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

bunkinet 20.09.2021 12:51

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