当前位置: 首页 > news >正文

限制Java线程池运行线程以及等待线程数量的策略

限制Java线程池运行线程以及等待线程数量的策略

对于java.util.concurrent.Executors所提供的FixedThreadPool,可以保证可以在内存中有固定数量的线程数运行。但是由于FixedThreadPool绑定的是LinkedBlockingQueue。队列的上限没有限制(默认上限为Integer.MAX_VALUE),不断的提交新的线程,会造成任务在内存中长时间的堆积。

我们有可能面临如下的场景,主线程不断地提交任务线程,希望有固定数量的在线程中运行,也不想造成线程在内存中大量的等待堆积。由此需要我们自己定义一个线程池策略。ThreadPoolExecutor为我们线程池的设置提供了很大的灵活性。

首先看FixedThreadPool的实现:

    public static ExecutorService More ...newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>(),
                                          threadFactory);
        }

可以看到,FixedThreadPool绑定的是LinkedBlockingQueue<Runnable>。我们需要做的第一个改造就是绑定有大小上线的BlockingQueue,在我的实现中绑定ArrayBlockingQueue<Runnable>并设置了size。

第二个是采用CallerRunsPolicy。ThreadPoolExecutor可以定义不同的任务拒绝策略。CallerRunsPolicy指的是当线程池拒绝该任务的时候,线程在本地线程直接execute。这样就限制了本地线程的循环提交流程。

    BlockingQueue<Runnable> workingQueue = new ArrayBlockingQueue<Runnable>(10);
    RejectedExecutionHandler rejectedExecutionHandler =
        new ThreadPoolExecutor.CallerRunsPolicy();
    ExecutorService threadPool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
        workingQueue, rejectedExecutionHandler);

    for (int i = 0; i < 100; i++) {
      
      threadPool.submit(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
          System.out.println("thread " + String.valueOf(threadNo) + " is called");
          Thread.sleep(10000);
          System.out.println("thread " + String.valueOf(threadNo) + " is awake");
          throw new Exception();
        }

      });
    }

代码中定义了大小为10的线程池,for循环提交了20个线程的时候,10个执行线程,10个线程放入了workingQueue。当提交到第21个线程的时候,会触发RejectedExecutionHandler。在这里我们配置了CallerRunsPolicy策略。所以会在主线程直接执行该线程。也就是说,在本程序中最多会有11个线程在执行,10个线程在等待。由此限制了线程池的等待线程数与执行线程数

相关文章:

  • 查看进程命令
  • 『Java』Servlet 最简教程
  • 获取微信openid
  • Obsolete此API即将移除
  • Colorful Image Colorization 的环境配置
  • 上下左右滚动插件
  • TableViewCell重影问题
  • HDU1048 The Hardest Problem Ever
  • CentOS下配置Hadoop集群:java.net.NoRouteToHostException: No route to host问题的解决
  • Linux 下vsftp配置文件
  • Flymeos插桩适配教程
  • 在liunx中构建DNS主从服务器的配置文档
  • httpd搭建虚拟主机、设置访问认证以及https相关的用法
  • 百度编辑器(Ueditor)最新版(1.4.3.3)插入锚点失败原因分析及BUG修复
  • Restore Volume 操作 - 每天5分钟玩转 OpenStack(60)
  • 【EOS】Cleos基础
  • Android单元测试 - 几个重要问题
  • Django 博客开发教程 8 - 博客文章详情页
  • download使用浅析
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • express如何解决request entity too large问题
  • gops —— Go 程序诊断分析工具
  • Gradle 5.0 正式版发布
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • jquery ajax学习笔记
  • JS基础之数据类型、对象、原型、原型链、继承
  • mysql常用命令汇总
  • Mysql数据库的条件查询语句
  • rabbitmq延迟消息示例
  • React中的“虫洞”——Context
  • Selenium实战教程系列(二)---元素定位
  • spring boot下thymeleaf全局静态变量配置
  • text-decoration与color属性
  • 爱情 北京女病人
  • 对超线程几个不同角度的解释
  • 精彩代码 vue.js
  • 利用jquery编写加法运算验证码
  • 前言-如何学习区块链
  • 使用docker-compose进行多节点部署
  • 问题之ssh中Host key verification failed的解决
  • 小程序开发之路(一)
  • 一个完整Java Web项目背后的密码
  • 找一份好的前端工作,起点很重要
  • Semaphore
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​水经微图Web1.5.0版即将上线
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (52)只出现一次的数字III
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据