Java 调度线程池执行器内部队列

Java scheduled threadpool executor internal queue

我想编写一个 运行 每 30 分钟运行一次的程序。我正在使用 java 计划的线程池执行器来处理我提交给执行器的任务。

我一直在看官方文档是怎么说的https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html

我 运行 进退两难。

假设我已经向队列提交了 5 个任务,并且在线程池中定义了 10 个线程。

  1. 是否有可能其中一项任务应执行两次

  2. 线程池执行程序是否确保任务在其中一个线程处理后被删除,或者我是否必须在处理完任务后自行删除任务。

删除任务是可取的,因为我不希望旧任务在 30 分钟后仍在队列中。

只会执行一次,执行器会自动移除

这没有明确记录,而 doc 暗示它:

Executes the given task sometime in the future.

Executors.newFixedThreadPool() 使用 LinkedBlockingQueue.

创建一个新的 ThreadPoolExecutor

来自 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;