为什么拒绝处理程序在队列溢出且所有线程都忙时不调用
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:
- In the default ThreadPoolExecutor.AbortPolicy, the handler throws a
runtime RejectedExecutionException upon rejection.
- 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.
- In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed
is simply dropped.
- 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
完成执行。
我已阅读 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:
- In the default ThreadPoolExecutor.AbortPolicy, the handler throws a runtime RejectedExecutionException upon rejection.
- 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.
- In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.
- 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
完成执行。