当前位置: 首页 > 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)
  • Google 是如何开发 Web 框架的
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • [译]CSS 居中(Center)方法大合集
  • docker容器内的网络抓包
  • JSDuck 与 AngularJS 融合技巧
  • Phpstorm怎样批量删除空行?
  • Promise面试题,控制异步流程
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 浅谈Golang中select的用法
  • 事件委托的小应用
  • 项目实战-Api的解决方案
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • Linux权限管理(week1_day5)--技术流ken
  • ​ubuntu下安装kvm虚拟机
  • #AngularJS#$sce.trustAsResourceUrl
  • (function(){})()的分步解析
  • (二)springcloud实战之config配置中心
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (篇九)MySQL常用内置函数
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)ORM
  • .gitignore文件---让git自动忽略指定文件
  • .htaccess配置重写url引擎
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .net6使用Sejil可视化日志
  • .Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
  • .NetCore项目nginx发布
  • .net打印*三角形
  • :中兴通讯为何成功
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @RequestBody的使用
  • [Angular 基础] - 指令(directives)
  • [Angular] 笔记 8:list/detail 页面以及@Input
  • [BSGS算法]纯水斐波那契数列
  • [BZOJ1053][HAOI2007]反素数ant
  • [C++核心编程](四):类和对象——封装
  • [Flutter]打包IPA
  • [HarekazeCTF2019]encode_and_encode 不会编程的崽