我是靠谱客的博主 执着翅膀,最近开发中收集的这篇文章主要介绍线程池的getActiveCount()不准确问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

线程池的getActiveCount()不准确问题

getActiveCount () 按照 javadocs 的说法是 “Returns the approximate number of threads that are actively executing tasks.” 也就是“返回正在执行任务的大致线程数”,请注意用词 approximate

查看一下源码:

 public int getActiveCount() {
     final ReentrantLock mainLock = this.mainLock;
     mainLock.lock();
     try {
         int n = 0;
         for (Worker w : workers)
             if (w.isLocked())
                 ++n;
         return n;
     } finally {
         mainLock.unlock();
     }
 }

该方法获取worker列表并计算被锁定的worker,返回计算结果。

当计数到达列表的末尾时,之前计算的一些worker可能已经完成了。(或者一些未使用的worker已经有了新任务。)

举个栗子:

public static void main(String[] args) throws Exception {
        // 创建线程池
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("test-%d").build();
        ThreadPoolExecutor  threadPool  = new ThreadPoolExecutor(
                11,
                11,
                65,
                TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>(),
                namedThreadFactory);


        int i = 0;
        do{
            while (threadPool.getActiveCount()>10){
                try {
                    Thread.sleep(1 * 1000);
                    System.out.println("reach max pool size:"+threadPool.getPoolSize()+", wait 1 second...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            threadPool.execute(()->{
                work();
            });
            i++;
        }while (i<1000000);
    }

    private static void work(){
        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+" is over");
    }

运行结果:
在这里插入图片描述

很奇怪,明明判断的是当活动线程数量大于10的时候,主线程就要等待一秒,理论上,threadPool.getActiveCount()是不可能大于11的,但是运行结果是threadPool.getActiveCount()一直在增加。

所以当线程多,或者线程不停的去执行任务时,这种计算得出来的结果并不是准确的,但这是多线程中固有的。举个栗子,假如线程池就是一个工厂,线程就是工人,你是工厂的boss,你想知道现在这个时刻有多少工人在干活,多少工人在休息,那你不能让一个工厂的所有工人都停下自己手头的工作,工厂停止运作然后去统计哪个在工作哪个在休息吧,所以当你的秘书给你统计的数据的时候,有些工人已经干完了手头的工作去休息了,有些工人或许有了新任务已经上岗干活了,时效性可能会导致结果的不准确。

解决办法

判断的时候主线程sleep一段时间:

  do{
        while (threadPool.getActiveCount()>10){
            try {
                Thread.sleep(1 * 1000);
                System.out.println("reach max pool size:"+threadPool.getPoolSize()+", wait 1 second...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        threadPool.execute(()->{
            work();
        });
        i++;
        Thread.sleep(1);  //当线程执行任务后,主线程休息1ms
    }while (i<1000000);

再看运行结果
在这里插入图片描述

始终是11

如有解释不严谨,欢迎指出,不吝赐教

最后

以上就是执着翅膀为你收集整理的线程池的getActiveCount()不准确问题的全部内容,希望文章能够帮你解决线程池的getActiveCount()不准确问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部