51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 808|回复: 0
打印 上一主题 下一主题

[转贴] Java 线程池四种拒绝策略

[复制链接]
  • TA的每日心情
    擦汗
    4 天前
  • 签到天数: 1042 天

    连续签到: 4 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-6-6 09:41:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    四种拒绝策略:

    预先配置
      配置线程池。
      · 核心线程和最大线程都尽量设置的小一点,分别设置成 1 和 2
      小码code阻塞队列设置固定长度的有界队列,长度为 1
      小码code线程工厂设置默认线程工厂
     // 核心线程数
      int corePoolSize = 1;
      // 最大线程数
      int maximumPoolSize = 2;
      // 线程存活时间
      long keepAliveTime = 10;
      // 线程存活时间单位
      TimeUnit unit = TimeUnit.SECONDS;
      // 有界队列 遵循 FIFO 原则
      BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1);
      // 线程工厂
      ThreadFactory threadFactory = Executors.defaultThreadFactory();

    创建线程任务
    创建线程任务,一个线程任务执行一秒:
    class TaskThread implements Runnable{
                     
                      private int i;
                      public TaskThread(int i) {
                              this.i = i;
                      }
                      @Override
                      public void run() {
                              try {
                                      TimeUnit.SECONDS.sleep(2);
                                      System.out.println("执行任务:" + i);
                              } catch (InterruptedException e) {
                                      e.printStackTrace();
                              }
                      }
              }

    拒绝策略一:AbortPolicy
    默认拒绝策略,拒绝任务并抛出任务:
    // 拒绝策略 默认拒绝策略,拒绝任务并抛出异常:
      RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
      ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
                                      maximumPoolSize,
                                      keepAliveTime,
                                      unit,
                                      workQueue,
                                      threadFactory,
                                      handler);
                      for (int i = 1; i <= 5; i++) {
                              try {
                                      threadPool.execute(new TaskThread(i));
                              } catch (Exception e) {
                                      System.out.println("【任务" + i + "】报错:" + e.getMessage());
                              }
                      }

      输出:
    【任务】4报错:Task com.test.controller.ThreadPoolController$TaskThread@5c0369c4 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
      【任务】5报错:Task com.test.controller.ThreadPoolController$TaskThread@31b7dea0 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
      执行任务:1
      执行任务:3
      执行任务:2

    最大线程数 + 阻塞队列 = 3,执行到4,5的时候就抛出错误。这里需要用 try catch 捕获异常。任务1、2、3正常执行。
     如果提交的任务都要执行,可以将抛出的错误任务存入在redis中,然后定时从redis中获取任务,再提交执行。

    拒绝策略二:CallerRunsPolicy
     调用线程运行多余的任务。
      更换拒绝策略,将上面的 AbortPolicy 换成 CallerRunsPolicy。
     RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

    执行任务,输出:
     执行任务:1
      执行任务:4
      执行任务:3
      执行任务:2
      执行任务:5

    最大线程数 + 阻塞队列 = 3,多余的任务还是继续被执行。
      拒绝策略三:DiscardPolicy
    拒绝任务,不会抛出错误。
      更换策略,将CallerRunsPolicy 换成DiscardPolicy:
    RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

    执行任务,输出:
    执行任务:1
      执行任务:3
      执行任务:2

    多余的线程任务提交被拒绝,而只执行最大线程数 + 阻塞队列 数量的任务,并且不会抛出错误。
      拒绝策略四:DiscardOldestPolicy
     只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入到阻塞队列中。
      更换策略,将DiscardPolicy 换成DiscardOldestPolicy:
    RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardOldestPolicy();

    执行任务,输出:
    执行任务:3
      执行任务:1
      执行任务:5

    任务的执行顺序是 核心线程数 —> 阻塞队列 —> 最大线程数,其中任务1,任务3提交成功。
      · 任务2因为在阻塞队列中,
      · 后面的任务4把任务2挤掉,
      · 任务5又把任务4挤掉,所以最后执行的是任务5。
      总结
    本文介绍了线程四种拒绝策略,当工作任务大于最大线程 + 阻塞队列会执行阻塞队列。
      · AbortPolicy 默认策略,拒绝任务,并抛出异常
      · CallerRunsPolicy 调用线程执行对于的任务
      · DiscardPolicy 拒绝任务,不会抛出异常
      · DiscardOldestPolicy 有多余的任务,把阻塞队列最老的任务丢弃,放入新的任务,直到没有新的任务。







    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-11 07:58 , Processed in 0.065048 second(s), 25 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表