博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程系列--“JUC线程池”05之 线程池原理(四)
阅读量:5268 次
发布时间:2019-06-14

本文共 7658 字,大约阅读时间需要 25 分钟。

转自:http://www.cnblogs.com/skywang12345/p/3512947.html

概要

本章介绍线程池的拒绝策略。内容包括:

  • 拒绝策略介绍
  • 拒绝策略对比和示例

转载请注明出处:

 

拒绝策略介绍

线程池的拒绝策略,是指当任务添加到线程池中被拒绝,而采取的处理措施。

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

线程池共包括4种拒绝策略,它们分别是:AbortPolicyCallerRunsPolicyDiscardOldestPolicyDiscardPolicy

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

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

 

拒绝策略对比和示例

下面通过示例,分别演示线程池的4种拒绝策略。

1. DiscardPolicy 示例

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.DiscardPolicy;public class DiscardPolicyDemo {    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
(CAPACITY)); // 设置线程池的拒绝策略为"丢弃" pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); // 新建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(); } }}

运行结果

task-0 is running.task-1 is running.

结果说明:线程池pool的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),这意味着"线程池能同时运行的任务数量最大只能是1"。

线程池pool的阻塞队列是,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
(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(); } }}

运行结果

task-0 is running.task-9 is running.

结果说明:将"线程池的拒绝策略"由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
(CAPACITY)); //note:这个容量是阻塞队列的容量大小 // 设置线程池的拒绝策略为"抛出异常" 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(); } }} 我的说明:总共可以容纳的线程容量是,线程池中最多1个,阻塞队列中最多1个。因此,不抛出异常的情况下,只允许开启两个线程。一个放在线程池中,另外一个放在阻塞队列中。上面总共创建了10个线程,因此没有地方存放,就会抛出异常。 避免抛出异常,可以修改阻塞队列的容量为9.

某一次)运行结果

java.util.concurrent.RejectedExecutionException    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774)    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768)    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656)    at AbortPolicyDemo.main(AbortPolicyDemo.java:27)task-0 is running.task-1 is running.

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

 

4. CallerRunsPolicy 示例

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.CallerRunsPolicy;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
(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(); } }}

某一次)运行结果

task-2 is running.task-3 is running.task-4 is running.task-5 is running.task-6 is running.task-7 is running.task-8 is running.task-9 is running.task-0 is running.task-1 is running.

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

转载于:https://www.cnblogs.com/Hermioner/p/9941500.html

你可能感兴趣的文章
机房收费系统——报表
查看>>
How to unshelve many shelves at same time
查看>>
table中checkbox选择多行
查看>>
动态链接库
查看>>
Magento开发文档(三):Magento控制器
查看>>
使用Docker官方的Django包【转】
查看>>
SuperSocket 学习
查看>>
给培训学校讲解ORM框架的课件
查看>>
此实现不是 Windows 平台 FIPS 验证的加密算法的一部分
查看>>
性能调优攻略
查看>>
线段树模板讲解
查看>>
ie6解决png图片透明问题
查看>>
瞬间的永恒
查看>>
H3C交换机DHCP&nbsp;Server配置的六个方面
查看>>
docker overlay网络实现
查看>>
mysql方言不支持blob类型解决方案
查看>>
2019-8-5 考试总结
查看>>
jquery javascript 回到顶部功能
查看>>
JS中实现字符串和数组的相互转化
查看>>
win10 进入安全模式的方法
查看>>