美文网首页
ThreadPoolExecutor的RejectedExecu

ThreadPoolExecutor的RejectedExecu

作者: 吃花生的小猴子 | 来源:发表于2018-01-02 17:51 被阅读0次

    java 线程池ThreadPoolExecutor的拒绝策略有:

        /**
         * A handler for rejected tasks that runs the rejected task
         * directly in the calling thread of the {@code execute} method,
         * unless the executor has been shut down, in which case the task
         * is discarded.
         */
        public static class CallerRunsPolicy implements RejectedExecutionHandler {
           ...
        }
    
        /**
         * A handler for rejected tasks that throws a
         * {@code RejectedExecutionException}.
         */
        public static class AbortPolicy implements RejectedExecutionHandler {
           ...
        }
    
        /**
         * A handler for rejected tasks that silently discards the
         * rejected task.
         */
        public static class DiscardPolicy implements RejectedExecutionHandler {
          ...
        }
    
        /**
         * A handler for rejected tasks that discards the oldest unhandled
         * request and then retries {@code execute}, unless the executor
         * is shut down, in which case the task is discarded.
         */
        public static class DiscardOldestPolicy implements RejectedExecutionHandler {
            ...
        }
    
    • CallerRunsPolicy : 当线程池和队列都满时,任务将会被任务的调用方线程执行,如果线程池关闭,那么任务将会被抛弃
    • AbortPolicy :当线程池和队列都满时,再有任务进来直接抛出RejectedExecutionException异常
    • DiscardPolicy: 当线程池和队列都满时,再有任务进来,默默的将任务抛弃
    • DiscardOldestPolicy: 当线程池和队列都满时,再有任务进来,抛弃最老的未处理的任务,然后重试该新进来的任务,如果线程池关闭,那么任务将会被抛弃

    我们来看一个例子:

    public static void main(String [] args) throws ExecutionException, InterruptedException {
    
    
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1,
                                                                            500,
                                                                            TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1),
    
                                                                            new ThreadPoolExecutor.CallerRunsPolicy()
                                                                            //new ThreadPoolExecutor.DiscardPolicy()
                                                                            //new ThreadPoolExecutor.DiscardOldestPolicy()
                                                                            //new ThreadPoolExecutor.AbortPolicy()
                                                                            );
    
            Future<String> taskOne = threadPoolExecutor.submit(()->{
    
                System.out.println("taskOne start...");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("taskOne 沉睡2秒结束...");
                return Thread.currentThread().getName();
            });
    
    
            Future<String> taskTwo = threadPoolExecutor.submit(()->{
    
                System.out.println("taskTwo start...");
    
                return Thread.currentThread().getName();
    
            });
    
            Future<String> taskThree = threadPoolExecutor.submit(()->{
    
                System.out.println("taskThree start...");
    
                return Thread.currentThread().getName();
            });
    
            System.out.println("taskOne:" + taskOne.get());
    
            System.out.println("taskTwo:" + taskTwo.get());
    
            System.out.println("taskThree:" + taskThree.get());
    
            threadPoolExecutor.shutdown();
        }
    

    上述例子中创建了一个核心线程池数与最大线程池数都为1,阻塞队列长度也为1的线程池。然后启动三个任务,其中第一个任务执行等待2秒。

    taskOne 占用了线程池中的唯一那个线程,taskTwo 进入了阻塞队列,这时队列已满,taskThree再进入线程池触发对应的策略。

    • 当使用CallerRunsPolicy策略时打印:
    taskOne start...
    taskThree start...
    taskOne 沉睡2秒结束...
    taskOne:pool-1-thread-1
    taskTwo start...
    taskTwo:pool-1-thread-1
    taskThree:main
    

    可以看出taskOne和taskTwo执行者都是线程池内的那个线程,而taskThree的执行线程则是调用taskThree的main函数主线程

    • 当使用DiscardPolicy()策略时打印:
    taskOne start...
    taskOne 沉睡2秒结束...
    taskOne:pool-1-thread-1
    taskTwo start...
    taskTwo:pool-1-thread-1
    

    默默抛弃策略不再打印taskThree 相关信息,并且程序在taskThree.get()处阻塞,线程池迟迟无法关闭。

    • 当使用DiscardOldestPolicy()策略时打印:
    taskOne start...
    taskOne 沉睡2秒结束...
    taskOne:pool-1-thread-1
    taskThree start...
    

    taskThree再进入线程池时,线程池根据策略把未执行的taskTwo给抛弃了,然后重试执行了taskThree,所以打印了taskThree start... ,但是,因为taskTwo 已被抛弃所以在调用taskTwo.get()时发生了阻塞。�所以没有System.out.println("taskThree:" + taskThree.get()); 相关的信息

    • 当使用AbortPolicy()策略时打印:
    Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@31cefde0 rejected from java.util.concurrent.ThreadPoolExecutor@439f5b3d[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]
    taskOne start...
    taskOne 沉睡2秒结束...
    taskTwo start...
    

    main主线程在taskThree的submit()时抛出异常,后面的信息都不打印了。

    相关文章

      网友评论

          本文标题:ThreadPoolExecutor的RejectedExecu

          本文链接:https://www.haomeiwen.com/subject/jfrqnxtx.html