Search code examples
javamultithreadingthreadpoolexecutor

workerCountOf() method in ThreadPoolExecutor java


I am trying to understand ThreadPoolExecutor class.I found some final variables declared in that class and unable to understand their use.

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;         //29
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;    //536870911     00011111111111111111111111111111

// RUN_STATE is stored in the high-order bits
private static final int RUNNING    = -1 << COUNT_BITS;         //-536870912    11100000000000000000000000000000
private static final int SHUTDOWN   =  0 << COUNT_BITS;         //0             00000000000000000000000000000000
private static final int STOP       =  1 << COUNT_BITS;         //536870912     00100000000000000000000000000000
private static final int TIDYING    =  2 << COUNT_BITS;         //1073741824    01000000000000000000000000000000
private static final int TERMINATED =  3 << COUNT_BITS;         //1610612736    01100000000000000000000000000000

Above are the final variables and their binary and decimal values.

Then I found two methods with use these varibles :

private static int runStateOf(int c)     { return c & ~CAPACITY; }  // RUN_STATE & ~CAPACITY = RUN_STATE
private static int workerCountOf(int c)  { return c & CAPACITY; }   // RUN_STATE & CAPACITY = 0
private static int ctlOf(int rs, int wc) { return rs | wc; }

The comments ahead of the methods, are the output that I observed.

Now in ThreadPoolExecutor#execute(runnable) method,

It is doing following calculation with a statement as If fewer than corePoolSize threads are running

int c = ctl.get();
if (workerCountOf(c) < corePoolSize)

I am trying to understand, in which case the value of workerCountOf(c) can be greater than corePoolSize. As you can see the initial value of ctl is RUNNING.

Also , there are methods to inc and dec ctl values atomically ,

private boolean compareAndIncrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect + 1);
}

private boolean compareAndDecrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect - 1);
}

Now lets say , 5 threads are running, so ctl = RUNNING + 5,

Even then workerCountOf(ctl.get()) = 0 ,

As ((RUNNING+5) & CAPACITY) = 0.

Can anybody explain me the reason of creating these final variable and their use?

How workerCountOf() method actually returning no of running threads?

I must be missing something.

Thanks


Solution

  • As you can see, Java uses the int ctl field to store both the current state of the pool and the number of threads. The state is stored in the higher three bits and all other bits are used to store the number of threads. Bitwise mask CAPACITY is used to separate them from each other:

    • CAPACITY = 00011111111111111111111111111111
    • ~CAPACITY = 11100000000000000000000000000000

    Thus,

    • ctl & CAPACITY preserves the lower 29 bits and zeroes the higher three bits; the result is the current threads number
    • ctl & ~CAPACITY preserves the higher three bits and zeroes all the others; the result is the pool run state

    As you correctly noticed, the running pool with five threads has ctl = (RUNNING + 5), that has binary representation 111000...000101. So, applying the CAPACITY mask zeroes the highest three bits and gives you the value 000000...000101, which is 5, not 0.