zoukankan      html  css  js  c++  java
  • java多线程系类:JUC线程池:05之线程池原理(四)(转)

    概要

    本章介绍线程池的拒绝策略。内容包括:
    拒绝策略介绍
    拒绝策略对比和示例

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html

    拒绝策略介绍

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

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

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

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

    拒绝策略对比和示例

    下面通过示例,分别演示线程池的4种拒绝策略。
    1. DiscardPolicy 示例
    2. DiscardOldestPolicy 示例
    3. AbortPolicy 示例
    4. CallerRunsPolicy 示例

    1. DiscardPolicy 示例

    复制代码
     1 import java.lang.reflect.Field;
     2 import java.util.concurrent.ArrayBlockingQueue;
     3 import java.util.concurrent.ThreadPoolExecutor;
     4 import java.util.concurrent.TimeUnit;
     5 import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
     6 
     7 public class DiscardPolicyDemo {
     8 
     9     private static final int THREADS_SIZE = 1;
    10     private static final int CAPACITY = 1;
    11 
    12     public static void main(String[] args) throws Exception {
    13 
    14         // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
    15         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
    16                 new ArrayBlockingQueue<Runnable>(CAPACITY));
    17         // 设置线程池的拒绝策略为"丢弃"
    18         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
    19 
    20         // 新建10个任务,并将它们添加到线程池中。
    21         for (int i = 0; i < 10; i++) {
    22             Runnable myrun = new MyRunnable("task-"+i);
    23             pool.execute(myrun);
    24         }
    25         // 关闭线程池
    26         pool.shutdown();
    27     }
    28 }
    29 
    30 class MyRunnable implements Runnable {
    31     private String name;
    32     public MyRunnable(String name) {
    33         this.name = name;
    34     }
    35     @Override
    36     public void run() {
    37         try {
    38             System.out.println(this.name + " is running.");
    39             Thread.sleep(100);
    40         } catch (Exception e) {
    41             e.printStackTrace();
    42         }
    43     }
    44 }
    复制代码

    运行结果

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

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

    2. DiscardOldestPolicy 示例

    复制代码
     1 import java.lang.reflect.Field;
     2 import java.util.concurrent.ArrayBlockingQueue;
     3 import java.util.concurrent.ThreadPoolExecutor;
     4 import java.util.concurrent.TimeUnit;
     5 import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;
     6 
     7 public class DiscardOldestPolicyDemo {
     8 
     9     private static final int THREADS_SIZE = 1;
    10     private static final int CAPACITY = 1;
    11 
    12     public static void main(String[] args) throws Exception {
    13 
    14         // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
    15         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
    16                 new ArrayBlockingQueue<Runnable>(CAPACITY));
    17         // 设置线程池的拒绝策略为"DiscardOldestPolicy"
    18         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
    19 
    20         // 新建10个任务,并将它们添加到线程池中。
    21         for (int i = 0; i < 10; i++) {
    22             Runnable myrun = new MyRunnable("task-"+i);
    23             pool.execute(myrun);
    24         }
    25         // 关闭线程池
    26         pool.shutdown();
    27     }
    28 }
    29 
    30 class MyRunnable implements Runnable {
    31     private String name;
    32     public MyRunnable(String name) {
    33         this.name = name;
    34     }
    35     @Override
    36     public void run() {
    37         try {
    38             System.out.println(this.name + " is running.");
    39             Thread.sleep(200);
    40         } catch (Exception e) {
    41             e.printStackTrace();
    42         }
    43     }
    44 }
    复制代码

    运行结果

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

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

    3. AbortPolicy 示例

    复制代码
     1 import java.lang.reflect.Field;
     2 import java.util.concurrent.ArrayBlockingQueue;
     3 import java.util.concurrent.ThreadPoolExecutor;
     4 import java.util.concurrent.TimeUnit;
     5 import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
     6 import java.util.concurrent.RejectedExecutionException;
     7 
     8 public class AbortPolicyDemo {
     9 
    10     private static final int THREADS_SIZE = 1;
    11     private static final int CAPACITY = 1;
    12 
    13     public static void main(String[] args) throws Exception {
    14 
    15         // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
    16         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
    17                 new ArrayBlockingQueue<Runnable>(CAPACITY));
    18         // 设置线程池的拒绝策略为"抛出异常"
    19         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
    20 
    21         try {
    22 
    23             // 新建10个任务,并将它们添加到线程池中。
    24             for (int i = 0; i < 10; i++) {
    25                 Runnable myrun = new MyRunnable("task-"+i);
    26                 pool.execute(myrun);
    27             }
    28         } catch (RejectedExecutionException e) {
    29             e.printStackTrace();
    30             // 关闭线程池
    31             pool.shutdown();
    32         }
    33     }
    34 }
    35 
    36 class MyRunnable implements Runnable {
    37     private String name;
    38     public MyRunnable(String name) {
    39         this.name = name;
    40     }
    41     @Override
    42     public void run() {
    43         try {
    44             System.out.println(this.name + " is running.");
    45             Thread.sleep(200);
    46         } catch (Exception e) {
    47             e.printStackTrace();
    48         }
    49     }
    50 }
    复制代码

    (某一次)运行结果

    复制代码
    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 示例

    复制代码
     1 import java.lang.reflect.Field;
     2 import java.util.concurrent.ArrayBlockingQueue;
     3 import java.util.concurrent.ThreadPoolExecutor;
     4 import java.util.concurrent.TimeUnit;
     5 import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
     6 
     7 public class CallerRunsPolicyDemo {
     8 
     9     private static final int THREADS_SIZE = 1;
    10     private static final int CAPACITY = 1;
    11 
    12     public static void main(String[] args) throws Exception {
    13 
    14         // 创建线程池。线程池的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。
    15         ThreadPoolExecutor pool = new ThreadPoolExecutor(THREADS_SIZE, THREADS_SIZE, 0, TimeUnit.SECONDS,
    16                 new ArrayBlockingQueue<Runnable>(CAPACITY));
    17         // 设置线程池的拒绝策略为"CallerRunsPolicy"
    18         pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    19 
    20         // 新建10个任务,并将它们添加到线程池中。
    21         for (int i = 0; i < 10; i++) {
    22             Runnable myrun = new MyRunnable("task-"+i);
    23             pool.execute(myrun);
    24         }
    25 
    26         // 关闭线程池
    27         pool.shutdown();
    28     }
    29 }
    30 
    31 class MyRunnable implements Runnable {
    32     private String name;
    33     public MyRunnable(String name) {
    34         this.name = name;
    35     }
    36     @Override
    37     public void run() {
    38         try {
    39             System.out.println(this.name + " is running.");
    40             Thread.sleep(100);
    41         } catch (Exception e) {
    42             e.printStackTrace();
    43         }
    44     }
    45 }
    复制代码

    (某一次)运行结果

    复制代码
    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之后,当有任务添加到线程池被拒绝时,线程池会将被拒绝的任务添加到"线程池正在运行的线程"中取运行。

  • 相关阅读:
    poj 3280 Cheapest Palindrome(区间DP)
    POJ 2392 Space Elevator(多重背包)
    HDU 1285 定比赛名次(拓扑排序)
    HDU 2680 Choose the best route(最短路)
    hdu 2899 Strange fuction (三分)
    HDU 4540 威威猫系列故事――打地鼠(DP)
    HDU 3485 Count 101(递推)
    POJ 1315 Don't Get Rooked(dfs)
    脱离eclipse,手动写一个servlet
    解析xml,几种方式
  • 原文地址:https://www.cnblogs.com/shenxiaoquan/p/6254619.html
Copyright © 2011-2022 走看看