美文网首页Refine-CI
JUC线程池(5):线程池拒绝策略

JUC线程池(5):线程池拒绝策略

作者: 放开那个BUG | 来源:发表于2018-12-02 10:53 被阅读6次

拒绝策略介绍

线程池的拒绝策略,是指当任务添加到线程池中被拒绝,所采取的措施。
当任务添加到线程池中之所以被拒绝,可能是由于:第一,线程池异常关闭。第二,任务数量超过线程池的最大限制。

线程池共包括4中拒绝策略,分别是:AbortPolicy,CallerRunsPolicy,DiscardOldestPolicy和DiscardPolicy。

  • AbortPolicy --- 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException异常
  • CallerRunsPolicy --- 当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。
  • DiscardOldestPolicy --- 当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。
  • DiscardPolicy --- 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。

线程池默认的处理策略是AbortPolicy。

拒绝策略的对比和示例

1.DiscardPolicy示例

package com.test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class DiscardPolicyTest {

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

    public static void main(String[] args) {
        // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),
        //"线程池"的阻塞队列容量为1(CAPACITY)。
        //"线程池"的拒绝策略为丢弃
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                THREAD_SIZE, THREAD_SIZE, 
                0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(CAPACITY), 
                new ThreadPoolExecutor.DiscardPolicy());
        
        
        //新建10个任务,添加到线程池中
        for(int i = 0; i < 10; i++){
            Runnable murun = new MyRunnable("task-" + i);
            poolExecutor.execute(murun);
        }
        
        poolExecutor.shutdown();
    }
    
    
}

class MyRunnable implements Runnable{

    private String name;
    
    public  MyRunnable(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        System.out.println(this.name + " is running");
    }
    
}

结果如下:


结果说明:

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

2.DiscardOldestPolicy示例

import java.lang.reflect.Field;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;

public class DiscardOldestPolicyDemo {

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

    public static void main(String[] args) throws Exception {

        // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
        ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(CAPACITY));
        // 设置线程池的拒绝策略为"DiscardOldestPolicy"
        pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());

        // 新建10个任务,并将它们添加到线程池中。
        for (int i = 0; i < 10; i++) {
            Runnable myrun = new MyRunnable("task-"+i);
            pool.execute(myrun);
        }
        // 关闭线程池
        pool.shutdown();
    }
}

class MyRunnable implements Runnable {
    private String name;
    public MyRunnable(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println(this.name + " is running.");
            Thread.sleep(200);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果如下:


结果说明:

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

3.AbortPolicy示例

import java.lang.reflect.Field;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
import java.util.concurrent.RejectedExecutionException;

public class AbortPolicyDemo {

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

    public static void main(String[] args) throws Exception {

        // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
        ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(CAPACITY));
        // 设置线程池的拒绝策略为"抛出异常"
        pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());

        try {

            // 新建10个任务,并将它们添加到线程池中。
            for (int i = 0; i < 10; i++) {
                Runnable myrun = new MyRunnable("task-"+i);
                pool.execute(myrun);
            }
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
            // 关闭线程池
            pool.shutdown();
        }
    }
}

class MyRunnable implements Runnable {
    private String name;
    public MyRunnable(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println(this.name + " is running.");
            Thread.sleep(200);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果如下:


说明:

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

CallerRunsPolicy示例

package com.test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CallerRunsPolicyDemo {

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

    public static void main(String[] args) throws Exception {

        // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
        ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(CAPACITY));
        // 设置线程池的拒绝策略为"CallerRunsPolicy"
        pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        // 新建10个任务,并将它们添加到线程池中。
        for (int i = 0; i < 10; i++) {
            Runnable myrun = new MyRunnable("task-"+i);
            pool.execute(myrun);
        }

        // 关闭线程池
        pool.shutdown();
    }
}

class MyRunnable implements Runnable {
    private String name;
    public MyRunnable(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        try {
            System.out.println(this.name + " is running.");
            Thread.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果如下:


结果说明:

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

参考资料

同上篇

相关文章

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • JUC线程池(5):线程池拒绝策略

    拒绝策略介绍 线程池的拒绝策略,是指当任务添加到线程池中被拒绝,所采取的措施。当任务添加到线程池中之所以被拒绝,可...

  • Java线程池拒绝策略

    【Java线程池拒绝任务策略】创建线程池可以指定拒绝策略如下: 一 拒绝时机1) 调用线程池的shutdown函数...

  • ThreadPoolExecutor

    线程池 拒绝策略 线程池的拒绝策略,即任务被添加到线程池中被拒绝而采取的处理措施。任务被拒绝的原因可能有: 线程池...

  • ThreadPoolExecutor的RejectedExecu

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

  • 线程池概述

    为什么要使用线程池? 线程池核心参数 线程池的几种拒绝策略 execute()和submit()的区别 线程池工作...

  • 线程池

    线程池执行过程 线程池生命周期 线程池分类 阻塞队列 拒绝策略 - ThreadPoolExecutor.Abor...

  • 线程池

    1、为什么要使用线程池2、线程池的工作原理3、线程池参数4、阻塞队列5、饱和策略6、向线程池提交任务7、线程池的状...

  • 并发--共享模型之工具

    线程池 1.1 自定义线程池 先自定义任务队列 自定义线程池 测试: 定义拒绝策略接口: 1.2 ThreadPo...

  • 信号量用法:锁

    用于dubbo线程池满的拒绝策略

网友评论

    本文标题:JUC线程池(5):线程池拒绝策略

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