ThreadPoolExecutor的RejectedExecu

2018-01-02  本文已影响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 {
        ...
    }

我们来看一个例子:

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再进入线程池触发对应的策略。

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函数主线程

taskOne start...
taskOne 沉睡2秒结束...
taskOne:pool-1-thread-1
taskTwo start...
taskTwo:pool-1-thread-1

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

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()); 相关的信息

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()时抛出异常,后面的信息都不打印了。

上一篇下一篇

猜你喜欢

热点阅读