Активные потоки в ExecutorService
-
09-06-2019 - |
Вопрос
Любые идеи о том, как определить количество активных потоков, работающих в данный момент в ExecutorService
?
Решение
Использовать ThreadPoolExecutor реализация и звонок getActiveCount() в теме:
int getActiveCount()
// Returns the approximate number of threads that are actively executing tasks.
Интерфейс ExecutorService не предоставляет для этого метода, это зависит от реализации.
Другие советы
Предполагая pool
— имя экземпляра ExecutorService:
if (pool instanceof ThreadPoolExecutor) {
System.out.println(
"Pool size is now " +
((ThreadPoolExecutor) pool).getActiveCount()
);
}
Проверьте исходный код 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()); } }
У меня была такая же проблема, поэтому я создал простой 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));
Поместите в поток статический изменчивый счетчик, который обновляется всякий раз, когда поток активируется и деактивируется.Также см. API.