线程池--拒绝策略RejectedExecutionHandler

线程池–拒绝策略RejectedExecutionHandler

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

当Executor已经关闭(即执行了executorService.shutdown()方法后),并且Executor将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法execute()中提交的新任务将被拒绝.
在以上述情况下,execute 方法将调用其 RejectedExecutionHandlerRejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) 方法。
线程池默认会采用的是defaultHandler策略。首先看defaultHandler的定义:

private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); // 使用默认的拒绝策略 
//丢弃任务并抛出RejectedExecutionException异常。
public static class AbortPolicy implements RejectedExecutionHandler {  
    public AbortPolicy() { }  
    // 抛出异常  
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
        throw new RejectedExecutionException("Task " + r.toString() +  " rejected from " +  e.toString());  
    }  
}  

接下来 是一个线程类 ,将实现四种拒绝策略的demo

package com.thread.exe.entity;

/**
 * Created by Andrew Feng on 2020/3/26
 */
public class RunnableTest implements Runnable {
    volatile int i;

    public RunnableTest(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println("start");
        System.out.println("task_" +i + " is running");
        System.out.println("end");
    }
}

看一下其他拒绝策略的具体实现。
1.DiscardPolicy示例(也是丢弃任务,但是不抛出异常。)

public class DiscardPolicyDemo {

    /**
     * 核心线程数
     */
    private static final int THREDSSIZE = 1;

    /**
     * 最大线程数
     */
    private static final int CAPACITY = 1;

    public static void main(String[] args) {
        //创建线程池  策略为丢弃
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(THREDSSIZE,THREDSSIZE,0, TimeUnit.SECONDS,new ArrayBlockingQueue<>(CAPACITY),new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 0; i < 10; i++){
            RunnableTest runnableTest = new RunnableTest(i);
            threadPoolExecutor.execute(runnableTest);
        }
        threadPoolExecutor.shutdown();
    }

}

线程池pool的”最大池大小”和”核心池大小”都为1(THREDSSIZE),这意味着”线程池能同时运行的任务数量最大只能是1”。
线程池pool的阻塞队列是[ArrayBlockingQueue],ArrayBlockingQueue是一个有界的阻塞队列,ArrayBlockingQueue的容量为1。这也意味着线程池的阻塞队列只能有一个线程池阻塞等待。   
根据”“中分析的execute()代码可知:线程池中共运行了2个任务。第1个任务直接放到Worker中,通过线程去执行;第2个任务放到阻塞队列中等待。其他的任务都被丢弃了!

2.DiscardOldestPolicy 示例(丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程))

public class DiscardOldestPolicyDemo {

    private static final int THREAD_SIZE = 1;

    private static final int CAPACITY = 1;

    public static void main(String[] args) {

        long keepAliveTime = 1;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(CAPACITY);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                THREAD_SIZE,THREAD_SIZE,keepAliveTime,unit,workQueue,handler);

        for (int i = 0; i < 10; i++) {
            RunnableTest runnableTest = new RunnableTest(CAPACITY);
            pool.execute(runnableTest);
        }

        pool.shutdown();
    }
}

运行结果:

start
task_1 is running
end
start
task_1 is running
end

将”线程池的拒绝策略”由DiscardPolicy修改为DiscardOldestPolicy之后,当有任务添加到线程池被拒绝时,线程池会丢弃阻塞队列中末尾的任务,然后将被拒绝的任务添加到末尾。

3.AbortPolicy 示例(丢弃任务并抛出RejectedExecutionException异常。)

public class AbortPolicyDemo {

    public static final int THREADS_SIZE = 1;

    public static final int CAPACITY = 1;

    public static void main(String[] args) throws Exception {
        long keepAliveTime = 1;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(CAPACITY);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                THREADS_SIZE,THREADS_SIZE,keepAliveTime,unit,workQueue,handler);
        try {
            for (int i = 0; i < 10;i++ ){
                RunnableTest runnableTest = new RunnableTest(i);
                pool.execute(runnableTest);
            }
        }catch(Exception e){
            System.out.println("异常为:"+e.toString());
        }finally {
            pool.shutdown();
        }
    }
}

(某一次运行结果)

异常为:java.util.concurrent.RejectedExecutionException: Task com.thread.exe.entity.RunnableTest@1540e19d rejected from java.util.concurrent.ThreadPoolExecutor@677327b6[Running, pool size = 1, active threads = 1, queued tasks = 1, completed tasks = 0]
start
task_0 is running
end
start
task_1 is running
end

将”线程池的拒绝策略”由DiscardPolicy修改为AbortPolicy之后,当有任务添加到线程池被拒绝时,会抛出RejectedExecutionException

4.CallerRunsPolicy 示例(由调用线程处理该任务)

public class CallerRunsPolicy {

    private static final int THREAD_SIZE = 1;
    private static final int CAPACITY = 1;

    public static void main(String[] args) {

        long keepAliveTime = 0;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable> (CAPACITY);
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

        //创建线程池 拒绝策略为 CallerRunsPolicy
        ThreadPoolExecutor pool = new ThreadPoolExecutor
                (THREAD_SIZE,THREAD_SIZE,keepAliveTime,unit,workQueue,handler);

        //新建10个任务,并添加到线程池中
        for (int i=0;i<10;i++) {
            RunnableTest myrun = new RunnableTest(i);
            pool.execute(myrun);
        }
        //关闭线程池
        pool.shutdown();
    }
}

某一次运行结果

start
task_2 is running
end
start
task_3 is running
end
start
task_4 is running
end
start
task_5 is running
end
start
task_6 is running
end
start
task_7 is running
end
start
task_8 is running
end
start
task_9 is running
end
start
task_0 is running
end
start
task_1 is running
end

将”线程池的拒绝策略”由DiscardPolicy修改为CallerRunsPolicy之后,当有任务添加到线程池被拒绝时,线程池会将被拒绝的任务添加到”线程池正在运行的线程”中取运行。

发布了33 篇原创文章 · 获赞 4 · 访问量 2708

猜你喜欢

转载自blog.csdn.net/qq_41650000/article/details/105239934