Java 线程池ExecutorService 等待队列问题

  • 1、首先看下Executor获取线程池,这样方式,可以设置线程池的大小,但是了解线程池的内部原理的情况下,这样的线程池可能会引起OOM,原因在于
    该线程池的等待队列最大长度默认为int的最大值,随口默写出来就是2147483647(2^31 -1,高中物理老师说过一句话,记住一些固定的数字可以预判一些问题)。线程池在提交任务时,如果线程池未达到最大线程数,则起线程执行任务,在达到最大值后,会放入等待队列,按默认的int最大值,很容易造成内存溢出。所以通常会选择自行构造线程池
ExecutorService threadPool = Executors.newFixedThreadPool(3);
  • 2、通过自行构建线程池,指定等待队列的长度。那么问题来了,虽然用的是BlockingQueue,但是往BlockingQueue放任务时,用的是offer(),方法,而不是阻塞的方法put();这样在队列满了之后,继续往队列放任务就会抛异常,线程池提供了rejection机制去处理这种情况,应用可以自定义如何处理队列满的情况,默认是直接丢弃。对于有些业务场景,我们宁愿阻塞等待,也不要无止境的放队列,然后让他失败。这时候需要再用一点奇技淫巧,用来保证在等待队列放置一定数量后,阻塞生成任务的线程,等到线程池里已经有任务处理完了再继续放入任务。
ExecutorService threadPool = new ThreadPoolExecutor(5, 5,
            0L, TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<Runnable>(5*2));
  • 3、还是使用2中自行构建的线程池,除此之外再定义一个blockQueue,最大长度为5,如下列代码。在while循环时,threadpool中的等待队列会逐渐增加最后稳定在5,并且此时与blockingQueue的长度一致,此时如果继续循环,便在blockingQueue.put(new Data())处阻塞,直到线程池中已有任务处理完。
BlockingQueue<Data> blockingQueue = new ArrayBlockingQueue<Data>(5);

    @Test
    public void testBlock() throws InterruptedException {
        int i=0;
        while(i<100){

            i++;
            blockingQueue.put(new Data());
//          System.out.println("blockingQueue.size():"+blockingQueue.size()+"  "+"threadpool:"+threadPool);
//          封装成task时并没有从blockingQueue中take,只有submit提交执行时才take,因此,等待队列中的task数目,就等于blockingQueue的长度了
            threadPool.submit( ()->{return process( blockingQueue.take());});
            System.out.println("blockingQueue.size():"+blockingQueue.size()+"  "+"threadpool:"+threadPool);
        }
        Thread.sleep(10000L);
        System.out.println("blockingQueue.size():"+blockingQueue.size()+"  "+"threadpool:"+threadPool);
    }


    public Result process(Data data) throws InterruptedException {
        Thread.sleep(300L);
        return new Result();
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java线程池 [toc] 什么是线程池 线程池就是有N个子线程共同在运行的线程组合。 举个容易理解的例子:有个线...
    石家志远阅读 1,339评论 0 6
  • 【JAVA 线程】 线程 进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者...
    Rtia阅读 2,777评论 2 20
  • 一.Java中的ThreadPoolExecutor类 java.uitl.concurrent.ThreadPo...
    谁在烽烟彼岸阅读 658评论 0 0
  • 现在预付100定金就送: 1:送价值168元的儿童摩托车一辆[玫瑰] 2:送价值688元史努比照片墙三件套[玫瑰]...
    简书米阅读 267评论 0 0
  • (若干年前的影评,修改一下重新发布。严重剧透,请谨慎阅读。) 小时候,我妈总跟我说:你是从阴沟里捡来的。我就总这么...
    张三四阅读 12,456评论 0 5