Активные потоки в ExecutorService

Есть идеи, как определить количество активных потоков, работающих в настоящее время в ExecutorService?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
67
0
75 480
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Используйте реализацию ThreadPoolExecutor и вызовите для нее getActiveCount ():

int getActiveCount() 
// Returns the approximate number of threads that are actively executing tasks.

Интерфейс ExecutorService не предоставляет для этого метода, это зависит от реализации.

Поместите статический энергозависимый счетчик в поток, который обновляется всякий раз, когда поток активируется и деактивируется. Также см. API.

Проверьте исходный код Executors.newFixedThreadPool():

return new ThreadPoolExecutor(nThreads, nThreads,
                              0L, TimeUnit.MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>());

ThreadPoolExecutor имеет метод getActiveCount (). Таким образом, вы можете либо преобразовать ExecutorService в ThreadPoolExecutor, либо использовать приведенный выше код напрямую для его получения. Затем вы можете вызвать getActiveCount().

Интерфейс ExecutorService не определяет метод для проверки количества рабочих потоков в пуле, поскольку это деталь реализации.

public int getPoolSize()
Returns the current number of threads in the pool.

Доступен в классе ThreadPoolExecutor

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class PoolSize {

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());
        System.out.println(executor.getPoolSize());
    }
}

Но для этого необходимо явно создать ThreadPoolExecutor, а не использовать фабрику Executors, которая возвращает объекты ExecutorService. Вы всегда можете создать свою собственную фабрику, возвращающую ThreadPoolExecutors, но у вас все равно останется плохая форма использования конкретного типа, а не его интерфейса.

Одна из возможностей - предоставить свою собственную ThreadFactory, которая создает потоки в известной группе потоков, которую вы затем можете подсчитать.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;


public class PoolSize2 {

    public static void main(String[] args) {
        final ThreadGroup threadGroup = new ThreadGroup("workers");

        ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
            public Thread newThread(Runnable r) {
                return new Thread(threadGroup, r);
            }
        });

        System.out.println(threadGroup.activeCount());
    }
}

это нормально тогда и только тогда, когда рабочая среда позволяет реализации установить группу для потока (например, Google App Engine)

VallaDanger 21.03.2016 04:08

Предполагая, что pool - это имя экземпляра ExecutorService:

if (pool instanceof ThreadPoolExecutor) {
    System.out.println(
        "Pool size is now " +
        ((ThreadPoolExecutor) pool).getActiveCount()
    );
}

У меня была такая же проблема, поэтому я создал простой Runnable для отслеживания экземпляра ExecutorService.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

public class ExecutorServiceAnalyzer implements Runnable
{
    private final ThreadPoolExecutor threadPoolExecutor;
    private final int timeDiff;

    public ExecutorServiceAnalyzer(ExecutorService executorService, int timeDiff)
    {
        this.timeDiff = timeDiff;
        if (executorService instanceof ThreadPoolExecutor)
        {
            threadPoolExecutor = (ThreadPoolExecutor) executorService;
        }
        else
        {
            threadPoolExecutor = null;
            System.out.println("This executor doesn't support ThreadPoolExecutor ");
        }

    }

    @Override
    public void run()
    {
        if (threadPoolExecutor != null)
        {
            do
            {
                System.out.println("#### Thread Report:: Active:" + threadPoolExecutor.getActiveCount() + " Pool: "
                        + threadPoolExecutor.getPoolSize() + " MaxPool: " + threadPoolExecutor.getMaximumPoolSize()
                        + " ####");
                try
                {
                    Thread.sleep(timeDiff);
                }
                catch (Exception e)
                {
                }
            } while (threadPoolExecutor.getActiveCount() > 1);
            System.out.println("##### Terminating as only 1 thread is active ######");
        }

    }
}

Вы можете просто использовать это со своим исполнителем, чтобы получить состояние ThreadPool.

Бывший

ExecutorService executorService = Executors.newFixedThreadPool(4);
    executorService.execute(new ExecutorServiceAnalyzer(executorService, 1000));

Другие вопросы по теме