This article is participating in the Java Theme Month – Java Debug Notes EventActive link
preface
Do not know when to start, I write articles become cautious, perhaps is afraid of their knowledge is not enough, perhaps is afraid of the depth is not enough. In fact, I clearly know is afraid that no one likes. I’m not going to write the rest of the article. Then I’m not afraid.
Java operator literacy
This article is mainly to practice the operators described above. If you don’t understand, please read this article first. Thank you.
About state values in source code in thread pools
The following is the thread pool source code about the state value, looking at a lot of operators are dizzy, the source code is completely unable to read. I’m stuck in a place I don’t understand until I figure it out.
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
Copy the code
This whole bunch of operators, just to serve the AtomicInteger CTL object in your code, the thread pool, that’s the value that holds two values by way of an operational offset. The core purpose is to reduce lock competition. Let’s take a look at AtomicInteger
AtomicInteger
Unsafe is an atomically updated int value. The underlying implementation uses the Unsafe compareAndSwapInt, which atomically sets the current value to the given updated value if == the expected value. Returns true on success. Returning False indicates that the actual value is not equal to the expected value.
The problem is, it’s just an Integer. How to save two? Doug Lea, the author, uses an operator to store two values. The Integer state is 32 bits. The TERMINATED state is RUNNING, SHUTDOWN, STOP, TIDYING, and TERMINATED. A maximum of seven threads are stored in three digits. Note: but including 0, plus a negative number, is a maximum of seven states. Because you want to make sure that your numbers are high, the low values are overwritten. The lower 29 bits hold the number of threads currently running (workerCountOf), and the maximum is 536870911. So the number of threads is limited by this value. I think no one should set up such a big bar! Hey hey
Just to get a sense of it
I’m going to peel these lines of code.
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// The higher 3 bits store the state, and the lower 29 bits store the number of threads currently running
private static final int COUNT_BITS = Integer.SIZE – 3;
ReentrantReadWriteLock = 16; // ReentrantReadWriteLock = 16; // ReentrantReadWriteLock = 16;
private static final int CAPACITY = (1 << COUNT_BITS) – 1;
// This is the key value, which is used to divide a value. CAPACITY is not easy to write, its binary, 1 is 29, 1111111111111111, if COUNT_BITS is 16, substitution (1 < < COUNT_BITS) – 1), is a low fill 16 0, minus 1, the result is 16 1, and if it is 2, That’s two ones.
Thread status value
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
The key is to look at this table, mainly the first three digits.
state | Binary (32 bits) | The former three | The decimal system |
---|---|---|---|
RUNNING | 11100000000000000000000000000000 | 111 | – 536870912. |
SHUTDOWN | 00000000000000000000000000000000 | 000 | 0 |
STOP | 00100000000000000000000000000000 | 100 | 536870912 |
TIDYING | 01000000000000000000000000000000 | 010 | 1073741824 |
TERMINATED | 01100000000000000000000000000000 | 011 | 1610612736 |
Calculates thread pool state
Looking back on the previous content, I think I should forget almost, I can look up the information, I never remember, my mind is for me to think.
The result is 1 only if the middle bit of both operands is 1, otherwise the result is 0.
~ is 0 becomes 1,1 becomes 0.(simply add one, then take the inverse) for example, 3, add one, is 4, take the inverse is -4. Please refer to my previous chapter for a more intuitive detailed calculation. Thanks – (· ω ·) Blue
Use the RUNNING state to calculate
Private static int runStateOf(int c) {//CAPACITY =536870911, After ~ is - 536870912 / / CAPACITY against hexadecimal is 11100000000000000000000000000000 / / RUNNING in hexadecimal is 11100000000000000000000000000000 / / results Hexadecimal is 11100000000000000000000000000000 / / todo: result is consistent with the RUNNING, knock, so here is take the high return of c & ~ CAPACITY; }Copy the code
Count the number of running threads
Let’s assume that the current number of threads RUNNING is 1 and the RUNNING status of the thread is RUNNING.
Private static int workerCountOf (int) c {/ / CAPACITY base is 00011111111111111111111111111111 / / 536870911-536870911 - thread count is 1 Hexadecimal is 11100000000000000000000000000001 / / result base is 00000000000000000000000000000001 / / & two operands, bit is 1, the result is 1, Otherwise the result is 0 //todo: key, so here is the low value. return c & CAPACITY; }Copy the code
Since CAPACITY is high at 000, (&) is 29 bits lower either way.
Update the thread pool running status
Or operator USES the symbol “|”, two bits as long as there is a 1, then the result is 1, otherwise 0.
private static int ctlOf(int rs, int wc) {
// For example, the current state is RUNNING and the number of threads is 1. So the value is
//1110 0000 0000 0000 0000 0000 0000 0001
//0000 0000 0000 0000 0000 0000
//1110 0000 0000 0000 0000 0000 0000 0001 //
return rs | wc; }
conclusion
Next post, write a thread pool by hand!
My knowledge is limited, if there is any wrong description, I would like to correct.
Look at thisLooks like you owe me a thumbs-up. Thank you.
Your praise is like the warm sun in winter, warming the heart.