线程池拒绝策略(超详细讲解)

线程池拒绝策略(超详细讲解)共用四种拒绝策略分别为 AbortPolicy CallerRunsPo DiscardPolic DiscardOldes 它们都是 下面的 MyRunnable 类用来描述一个任务

大家好,欢迎来到IT知识分享网。

线程池拒绝策略(超详细讲解)

共用四种拒绝策略分别为: AbortPolicy,CallerRunsPolicy,DiscardPolicy,DiscardOldestPolicy 它们都是 ThreadPoolExecutor 类下的静态内部类,并都实现了 RejectExecutionHandler 接口

线程池拒绝策略(超详细讲解)

下面的 MyRunnable 类用来描述一个任务  

class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + " 正在执行 " + System.currentTimeMillis()); try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }

1. AbortPolicy:

触发该拒绝策略时,会直接抛出 RejectedExecutionException 异常;

 public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.AbortPolicy()); MyRunnable runnable1 = new MyRunnable(); MyRunnable runnable2 = new MyRunnable(); MyRunnable runnable3 = new MyRunnable(); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); }

线程池拒绝策略(超详细讲解)

抛出异常之后,此时新的任务也无法继续完成了,但是在阻塞队列中存在的任务并非是新的任务;所以等待 2 秒(因为 MyRunnable 接口 重写的 run 方法 sleep 了 2 秒)之后,此时线程会继续执行阻塞队列中的任务;看下面这个情况:

 Thread.sleep(3000); System.out.println(System.currentTimeMillis()); MyRunnable runnable4 = new MyRunnable(); executor.execute(runnable4);

在上述代码的基础上,再添加以上代码,再次执行程序:

线程池拒绝策略(超详细讲解)

可以看到,本来应该是执行完阻塞队列的任务之后,主线程休眠 3 秒,执行阻塞队列的任务会休眠2 秒,所以主线程休眠 3 秒之后,线程应该是空闲状态,理应继续执行下面的逻辑,打印当前时间戳,并执行任务 4,但是使用的是 AbortPolicy 拒绝策略,抛出异常后,后续任务也不会执行了;

2. CallerRunsPolicy:

触发该拒绝策略时,添加的任务由添加任务的线程执行;

public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.CallerRunsPolicy()); MyRunnable runnable1 = new MyRunnable(); MyRunnable runnable2 = new MyRunnable(); MyRunnable runnable3 = new MyRunnable(); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); }

线程池拒绝策略(超详细讲解)

由执行结果可以看到,第一个任务由线程池的核心线程执行, 第二个任务进入阻塞队列并等待执行,第三个任务会触发拒绝策略 CallerRunsPolicy,由添加任务的线程执行,显然此处是 main 线程添加的任务,故由 main 线程执行,核心线程经过 2 秒执行完毕后,继续执行阻塞队列中的任务;此时,如果有新任务再次添加,结果又会怎么样呢?同样添加上述代码,测试结果如下:

 Thread.sleep(3000); System.out.println(System.currentTimeMillis()); MyRunnable runnable4 = new MyRunnable(); executor.execute(runnable4);

线程池拒绝策略(超详细讲解)

可以看出,触发 CallerRunsPolicy 拒绝策略之后,再有新任务来时,仍然能正常执行;

3. DiscardOldestPolicy:

触发该拒绝策略时,会丢弃一个阻塞队列中最古老的任务,并将新的任务加入到阻塞队列中;

为了验证该拒绝策略,对 MyRunnable 类添加一个属性 name,并对 run 方法进行调整:

class MyRunnable implements Runnable{ private String name; public MyRunnable(String name){ this.name = name; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " 正在执行 " + this.name + " 时间 " + System.currentTimeMillis()); try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
 public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardOldestPolicy()); MyRunnable runnable1 = new MyRunnable("第一个任务"); MyRunnable runnable2 = new MyRunnable("第二个任务"); MyRunnable runnable3 = new MyRunnable("第三个任务"); MyRunnable runnable4 = new MyRunnable("第四个任务"); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); executor.execute(runnable4); Thread.sleep(3000); System.out.println("所有任务执行完毕"); }

线程池拒绝策略(超详细讲解)

由代码及运行结果可以看出,首先第一个任务来时,由核心线程执行,第二个任务来时,进入阻塞队列,第三个任务来时,线程全部都不空闲,并且阻塞队列已满,故会触发拒绝策略,丢弃第二个任务,并将第三个任务放入阻塞队列,第四个任务来时,仍然会触发拒绝策略,丢弃第三个任务,并将第四个任务放入阻塞队列,之后核心线程执行完第一个任务之后,会继续执行阻塞队列中的第四个任务;

4. DiscardPolicy:

触发该拒绝策略时,会直接丢弃掉新来的任务,即直接忽略;

public static void main(String[] args) throws InterruptedException { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardPolicy()); MyRunnable runnable1 = new MyRunnable("第一个任务"); MyRunnable runnable2 = new MyRunnable("第二个任务"); MyRunnable runnable3 = new MyRunnable("第三个任务"); executor.execute(runnable1); executor.execute(runnable2); executor.execute(runnable3); Thread.sleep(3000); System.out.println("所有任务执行完毕"); }

线程池拒绝策略(超详细讲解)

由代码及运行结果可以看出,首先第一个任务来时,由核心线程执行,第二个任务来时,进入阻塞队列,第三个任务来时,会触发 DiscardPolicy 拒绝策略,直接丢弃第三个任务,等待核心线程执行完第一个任务之后,会继续执行阻塞队列中的第二个任务;

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/114521.html

(0)
上一篇 2025-12-08 16:00
下一篇 2025-12-08 16:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信