ThreadPool——拒绝策略

当新加任务无法进入等待线程且线程数达到上限时需要根据拒绝策略拒绝任务  使用Executors类的静态方法创建线程池的时候默认AbortPolicy策略

AbortPolicy中止策略

使用该策略时在饱和时会抛出RejectedExecutionException(继承自RuntimeException),调用者可捕获该异常自行处理。

DiscardPolicy抛弃策略

不做任何处理直接抛弃任务

DiscardOldestPolicy抛弃旧任务策略

先将阻塞队列中的头元素出队抛弃,再尝试提交任务。如果此时阻塞队列使用PriorityBlockingQueue优先级队列,将会导致优先级最高的任务被抛弃,因此不建议将该种策略配合优先级队列使用。

CallerRunsPolicy调用者运行

既不抛弃任务也不抛出异常,直接运行任务的run方法,换言之将任务回退给调用者来直接运行。使用该策略时线程池饱和后将由调用线程池的主线程自己来执行任务,因此在执行任务的这段时间里主线程无法再提交新任务,从而使线程池中工作线程有时间将正在处理的任务处理完成。

public class ThreadPoolExecutorDemo {

    private static int produceTaskSleepTime = 2;
    private static int produceTaskMaxNumber = 10;
    public static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,
            4,
            3,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(3),
            new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) {

        for (int i = 1; i <= produceTaskMaxNumber; i++) {
            try {
                // 产生一个任务,并将其加入到线程池
                String task = "task@ " + i;
                threadPool.execute(new ThreadPoolTask(task));
                System.out.println("put " + task + "   " + System.currentTimeMillis() + "线程池中线程数目:" + threadPool.getPoolSize() + ",队列中等待执行的任务数目:" +
                        threadPool.getQueue().size() + ",已执行完的任务数目:" + threadPool.getCompletedTaskCount());

                // 便于观察,等待一段时间
                Thread.sleep(produceTaskSleepTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        ;
    }
}

class ThreadPoolTask implements Runnable, Serializable {
    private static final long serialVersionUID = 0;
    private static int consumeTaskSleepTime = 2000;
    // 保存任务所需要的数据
    private Object threadPoolTaskData;

    ThreadPoolTask(Object tasks) {
        this.threadPoolTaskData = tasks;
    }

    public void run() {
        // 处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句
        System.out.println(Thread.currentThread().getName() + "     start .." + threadPoolTaskData + "   " + System.currentTimeMillis());
        try {
            // //便于观察,等待一段时间
            Thread.sleep(consumeTaskSleepTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        threadPoolTaskData = null;
    }

    public Object getTask() {
        return this.threadPoolTaskData;
    }
}

输出结果:通过结果可以看出不同的策略影响线程池的运行轨迹

put task@ 1 1541041438057线程池中线程数目:1,队列中等待执行的任务数目:0,已执行完的任务数目:0
put task@ 2 1541041438065线程池中线程数目:2,队列中等待执行的任务数目:0,已执行完的任务数目:0
put task@ 3 1541041438068线程池中线程数目:2,队列中等待执行的任务数目:1,已执行完的任务数目:0
put task@ 4 1541041438072线程池中线程数目:2,队列中等待执行的任务数目:2,已执行完的任务数目:0
put task@ 5 1541041438074线程池中线程数目:2,队列中等待执行的任务数目:3,已执行完的任务数目:0
put task@ 6 1541041438078线程池中线程数目:3,队列中等待执行的任务数目:3,已执行完的任务数目:0
put task@ 7 1541041438081线程池中线程数目:4,队列中等待执行的任务数目:3,已执行完的任务数目:0
main start ..task@ 8 1541041438084
pool-1-thread-1 start ..task@ 1 1541041438086
pool-1-thread-2 start ..task@ 2 1541041438086
pool-1-thread-3 start ..task@ 6 1541041438103
pool-1-thread-4 start ..task@ 7 1541041438112
pool-1-thread-2 start ..task@ 3 1541041440104
pool-1-thread-1 start ..task@ 4 1541041440104
put task@ 8 1541041440104线程池中线程数目:4,队列中等待执行的任务数目:1,已执行完的任务数目:2
pool-1-thread-3 start ..task@ 5 1541041440154
put task@ 9 1541041440179线程池中线程数目:4,队列中等待执行的任务数目:1,已执行完的任务数目:3
pool-1-thread-4 start ..task@ 9 1541041440179
put task@ 10 1541041440232线程池中线程数目:4,队列中等待执行的任务数目:1,已执行完的任务数目:4
pool-1-thread-2 start ..task@ 10 1541041442116

发表评论

电子邮件地址不会被公开。 必填项已用*标注