What does Current Thread Busy means?

Published by

on

TL; DR

“Current Thread Busy” metric displays how many active threads are in the pool. This shows the value of ThreadPoolExecutor.getActiveCount().

Which reflects the number of the threads that are running their tasks (= the number of the requests that are being currently handled), not necessary has to be RUNNABLE state.

Details

As seen from above code, ThreadPoolExecutor.getActiveCount() returns the count of workers whose isLocked() is true.

Q) Then when does the isLocked() becomes true?

When we search for the isLocked() method, it shows there are lock() method which is being called from java.util.concurrent.ThreadPoolExecutor#runWorker.

When there are requests coming in, those requests will get queued up in the workQueue, which will be polled from the workers(threads).

And then when the thread gets task successfully from the queue, it’ll call the lock() method which will make isLocked() as true.

Therefore, when the worker thread gets the task from the work queue, it becomes an ‘Active’ thread.

Q) What is the state of the ‘Active’ thread?

At first I thought the “Active” thread has to do something with the thread state, which means only the RUNNABLE state threads are counted as the “Active” threads.

However, it turned out the thread state has nothing to do with the count of “Active” threads. Let’s take a look at below two examples of WAITING threads’ threaddumps.

WAITING Thread A
WAITING Thread B

Although those two threads are both in the same WAITING state, Thread A is considered to be not-Active thread while B is.

This is because if you look at the stacktrace of the threads,

  • Thread A is waiting to get the task from the work queue inside of ThreadPoolExecutor.getTask => This means the thread is not active yet.
  • Thread B is waiting for a lock while executing a task which basically handles requests inside from the http client library. => This means the thread has its own task assigned, which means it is ‘Active’.

With that being said, the ThreadPoolExecutor.getActiveCount() will include Thread B only.

Example Code

public static void main(String args[]) throws InterruptedException {
		ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);

		executorService.execute(() -> {
			System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getId());
			try {
				Thread.sleep(1000000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});

		executorService.execute(() -> {
			System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getId());
			try {
				Thread.sleep(1000000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});

		executorService.execute(() -> {
			System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getId());
			try {
				Thread.sleep(1000000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});

		executorService.execute(() -> {
			System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getId());
			int i = 0;
			while(true) {
				i++;
			}
		});

		executorService.execute(() -> {
			System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getId());
		});

		executorService.execute(() -> {
			System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getId());
			int i = 0;
			i++;
		});

		while(true) {
			System.out.println("Current Active Thread Count : " + executorService.getActiveCount());
			Thread.sleep(1000);
		}
pool-1-thread-1 : 19
pool-1-thread-2 : 20
pool-1-thread-3 : 21
pool-1-thread-4 : 22
pool-1-thread-5 : 23
Current Active Thread Count : 5
pool-1-thread-6 : 24
Current Active Thread Count : 4
Current Active Thread Count : 4
Current Active Thread Count : 4

ThreadPoolExecutor.getActiveCount() returns 4 which includes 3 SLEEPING threads + 1 RUNNABLE thread.

Reference

Leave a comment