Reputation: 702
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
Upvotes: 4
Views: 547
Reputation: 6197
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 numberctl & ~CAPACITY
preserves the higher three bits and zeroes all the others; the result is the pool run stateAs 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.
Upvotes: 5