为什么拒绝处理程序在队列溢出且所有线程都忙时不调用

Why rejection handler doesn't invoke when queue overflowed and all threads busy

我已阅读 java 文档中关于 ThreadPoolExecutor 的手册:

让我们看看这部分:

Rejected tasks

New tasks submitted in method execute(java.lang.Runnable) will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated. In either case, the execute method invokes the RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) method of its RejectedExecutionHandler. Four predefined handler policies are provided:

  1. In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.
  2. In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
  3. In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.
  4. In ThreadPoolExecutor.DiscardOldestPolicy, if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.) It is possible to define and use other kinds of RejectedExecutionHandler classes. Doing so requires some care especially when policies are designed to work only under particular capacity or queuing policies.

为了检查粗体文本,我试着写了一个小例子:

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(1),
                Executors.defaultThreadFactory(),
                new RejectedExecutionHandler() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        System.out.println("rejected");
                    }
                });
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("work  started");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("work  finished");
            }
        };
        //execute
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.execute(runnable);
        threadPoolExecutor.shutdown();

此代码输出:

work  started
work  finished
work  started
work  finished

我希望在控制台中看到 "rejected" 输出。

你能解释一下这种行为吗?

new ArrayBlockingQueue<Runnable>(1) 可以容纳一个可运行的。 第三次调用 threadPoolExecutor.execute(runnable) 应该会给你预期的结果。由于第一个调用立即从队列中删除,第二个调用被保留在队列中,直到第一个 runnable 完成执行。