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

时间:2018-10-31 13:15:24

标签: java threadpoolexecutor

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

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

,我陷入了困境。

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

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

  2. 线程池执行程序是否确保在线程之一处理完任务后将其删除,或者一旦处理完任务后我必须自己删除该任务。

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

2 个答案:

答案 0 :(得分:1)

它只会执行一次,执行者会自动将其删除。

这没有明确记录,而doc暗示了这一点:

  

将来某个时间执行给定的任务。

答案 1 :(得分:1)

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;