文档章节

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

zjg23
 zjg23
发布于 2016/10/09 14:06
字数 514
阅读 13
收藏 0

对于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循环提交了100个线程的时候,10个执行线程,10个线程放入了workingQueue。当提交到第21个线程的时候,会触发RejectedExecutionHandler。在这里我们配置了CallerRunsPolicy策略。所以会在主线程直接执行该线程。也就是说,在本程序中最多会有11个线程在执行,10个线程在等待。由此限制了线程池的等待线程数与执行线程数。

本文转载自:https://segmentfault.com/a/1190000005876711

共有 人打赏支持
zjg23
粉丝 18
博文 120
码字总数 40282
作品 0
济南
程序员
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
高级面试题总结—线程池还能这么玩?

前言 面试中我们经常会遇到多线程和线程池的问题,究竟如何回答呢?今天关于Java中的线程池,我们就来学习一下。 什么是线程池 线程池是指在初始化一个多线程应用程序过程中创建一个线程集合...

codeGoogle
07/20
0
0
Java线程框架_Executor

Executor 框架是 juc 里提供的线程池的实现。前两天看了下 Executor 框架的一些源码,做个简单的总结。 线程池大概的思路是维护一个的线程池用于执行提交的任务。我理解池的技术的主要意义有...

天呀鲁哇
2015/02/05
0
0
java并发编程实战 第八章 线程池的使用

一、在任务与执行策略直接的隐性耦合 Executor框架可以将任务的提交与任务的执行策略解耦。 有些类型的任务需要明确地指定执行策略,包括: 依赖性任务 大多数行为正确的任务都是独立的:他们...

南方之木
04/21
0
0
学习Java基础知识,打通面试关~十六自定义线程池

在上篇文章中我们了解到了Java是怎么来建立自带的线程池的,虽然Java中提供了多种线程池,但是我们还是在某些场景下需要实现自己的线程池操作。 新建立线程 在阿里的指导手册里面,也是建议自...

super糖
07/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

angular指令监听ng-repeat渲染完成后执行自定义事件方法

今天工作中遇到需要用到ng-repeat遍历渲染完后执行某个操作,angular本身并没有提供监听ng-repeat渲染完成的指令,所以需要自己创建自定义指令。 在ng-repeat模板实例内部会暴露出一些特殊属...

孟飞阳
40分钟前
1
0
URLEncoder和URLDecoder

public static void main(String[] args) { String str1 = "https://test1-life.pingan.com/ilifecore/productMall/loading.html?productId=8000000241&channelCode=XCX00001&productCode=00......

鬼才王
50分钟前
2
0
对象及变量的并发访问-第一篇

方法内部的变量为线程安全变量 “非线程安全”问题存在于“共享变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题,所得结果也就是“线程安全”的。 package chaprer3;/**...

简心
51分钟前
1
0
程序媛眼中的程序猿原来是这样子的!

一直都想写一篇关于描述程序员的文章,但是一直没能开头,一来因为文笔不好,更主要的原因是貌似对程序员既熟悉又不熟悉,很怕写出来的是以偏概全,给大家造成对程序员的既定印象,不过,管他...

Java小铺
今天
1
0
bean标签

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 bean标签 bean标签中的init-method属性,该属性...

凯哥学堂
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部