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

时间:2017-02-27 11:25:12

标签: java multithreading concurrency threadpool threadpoolexecutor

我已阅读过java doc ThreadPoolExecutor

的手册

让我们看看这部分:

  

拒绝的任务

     

方法execute(java.lang.Runnable)中提交的新任务将是   当Executor关闭时,拒绝,当时,   Executor对最大线程和工作队列使用有限边界   容量,并且已经饱和。在任何一种情况下,execute方法都会调用   RejectedExecutionHandler.rejectedExecution(java.lang.Runnable,   它的java.util.concurrent.ThreadPoolExecutor)方法   RejectedExecutionHandler。四个预定义的处理程序策略   提供:

     
      
  1. 在默认的ThreadPoolExecutor.AbortPolicy中,处理程序抛出一个   拒绝后运行时RejectedExecutionException。
  2.   
  3. 在ThreadPoolExecutor.CallerRunsPolicy中,调用的线程   执行自己运行任务。这提供了简单的反馈   控制机制将减慢新任务的速度   提交。
  4.   
  5. 在ThreadPoolExecutor.DiscardPolicy中,无法执行的任务   简直就是放弃了。
  6.   
  7. 在ThreadPoolExecutor.DiscardOldestPolicy中,如果是   执行程序没有关闭,工作队列头部的任务是   丢弃,然后重试执行(可能再次失败,   导致这种情况重复。)   可以定义和使用其他类型的   RejectedExecutionHandler类。这样做需要一些小心   特别是当政策被设计为仅在特定情况下工作时   容量或排队政策。
  8.   

要查看粗体文字,我试着写一个小例子:

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

我希望看到&#34;拒绝&#34;在控制台输出。

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

1 个答案:

答案 0 :(得分:3)

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