[Java technology exploration, naked speech of a 34 year old java programmer

Posted by php_blob on Mon, 27 Dec 2021 05:09:56 +0100

for (TreeNode<K,V> x = b, next; x != null; x = next) {

    next = (TreeNode<K,V>)x.next; //The next value of the incoming node is assigned to the next node of the current treebin node, which is used for data synchronization

    x.left = x.right = null; //null both the left subtree and the right subtree

    if (r == null) {

        x.parent = null;//Parent node is empty

        x.red = false; // Node that does not belong to red subtree

        r = x; //Store the red node temporarily for the next recycling

    }

    else {

        K k = x.key; //If it is not the root node, it is the next subtree node (belonging to the next value)

        int h = x.hash; // If it is not the root node, take out the hash value

        Class<?> kc = null;

        for (TreeNode<K,V> p = r;;) {

            int dir, ph; //

            K pk = p.key;//Get the key value of the root node 

            if ((ph = p.hash) > h) // Get the hash value and judge whether it belongs to the hash value less than the root node

                dir = -1; //It belongs to the left subtree,

            else if (ph < h) // Otherwise, it belongs to the right subtree

                dir = 1;

            else if ((kc == null &&

                      (kc = comparableClassFor(k)) == null) ||

                     (dir = compareComparables(kc, k, pk)) == 0)

				// When the hash values are equal, compare the class and key values

                dir = tieBreakOrder(k, pk);

                TreeNode<K,V> xp = p;

            if ((p = (dir <= 0) ? p.left : p.right) == null) {

				// Judge whether the comparison result is less than zero and the left and right subtrees are null

                x.parent = xp;// Assign a value to the parent node

                if (dir <= 0)

                    xp.left = x; // Judge whether it belongs to the left subtree (< = 0)

                else

                    xp.right = x;// Judge whether it belongs to the right subtree (> 0)

				// Carry out the balanced insertion mechanism (in fact, establish a balanced relationship)

                r = balanceInsertion(r, x);

                break;

            }

        }

    }

}

this.root = r; // Root node

assert checkInvariants(root);

}



### [](https://gitee.com/vip204888/java-p7)ForwardingNode



One for connecting two table Node class for. It contains a nextTable Pointer to the next table.**And this node's key value next All pointers are null,its hash Value is-1. It's defined here find The method is from nextTable Instead of searching with itself as the head node, query the node in**



/**

  • A node inserted at head of bins during transfer operations.

*/

static final class ForwardingNode<K,V> extends Node<K,V> {

final Node<K,V>[] nextTable;

ForwardingNode(Node<K,V>[] tab) {

    super(MOVED, null, null, null);

    this.nextTable = tab;

}

// Loop through to find the corresponding hash and key values

Node<K,V> find(int h, Object k) {

    // loop to avoid arbitrarily deep recursion on forwarding nodes

    outer: for (Node<K,V>[] tab = nextTable;;) {

        Node<K,V> e; int n;

		// If it cannot be located or located to null, it returns directly

        if (k == null || tab == null || (n = tab.length) == 0 ||

            (e = tabAt(tab, (n - 1) & h)) == null)

            return null;

        for (;;) {

            int eh; K ek;

			// Traverse to find and compare the hash value and key value to analyze whether they are equal.

            if ((eh = e.hash) == h &&

                ((ek = e.key) == k || (ek != null && k.equals(ek))))

				// Return directly after finding

                return e;

			//If the hash value is - 1 or - 2 

            if (eh < 0) {

				// If it is forwardingNode, it means - 1

                if (e instanceof ForwardingNode) {

					//Get directly to the next table.

                    tab = ((ForwardingNode<K,V>)e).nextTable;

                    continue outer;

                }

                else

                    return e.find(h, k);

            }

			//Until null, return directly

            if ((e = e.next) == null)

                return null;

        }

    }

}

}



[](https://gitee.com/vip204888/java-p7)Unsafe and CAS

-----------------------------------------------------------------------------



> **stay ConcurrentHashMap You can see it everywhere Unsafe, Extensive use Unsafe.compareAndSwapXXX This method uses a CAS The algorithm realizes the operation of modifying the value without lock, which can greatly reduce the performance consumption of lock agent**. 



> The basic idea of this algorithm is to constantly compare whether the variable value in the current memory is equal to a variable value you specify. If it is equal, accept the modified value you specify, otherwise reject your operation.



Because the value in the current thread is not the latest value, your modification is likely to overwrite the modification results of other threads. This is similar to the optimistic lock, SVN The idea is similar.



### []( https://gitee.com/vip204888/java-p7 )Unsafe static block



unsafe The code block controls the modification of some attributes, such as the most commonly used ones SIZECTL .  In this version concurrentHashMap In, it is widely used CAS Method to modify variables and attributes. utilize CAS Lock free operation can greatly improve performance.



//The offset of each field attribute can be obtained from the corresponding data object by offset + first address

private static final sun.misc.Unsafe U;

private static final long SIZECTL;

private static final long TRANSFERINDEX;

private static final long BASECOUNT;

private static final long CELLSBUSY;

private static final long CELLVALUE;

private static final long ABASE;

private static final int ASHIFT;

static {

try {

    U = sun.misc.Unsafe.getUnsafe();

    Class<?> k = ConcurrentHashMap.class;

    SIZECTL = U.objectFieldOffset

        (k.getDeclaredField("sizeCtl"));

    TRANSFERINDEX = U.objectFieldOffset

        (k.getDeclaredField("transferIndex"));

    BASECOUNT = U.objectFieldOffset

        (k.getDeclaredField("baseCount"));

    CELLSBUSY = U.objectFieldOffset

        (k.getDeclaredField("cellsBusy"));

    Class<?> ck = CounterCell.class;

    CELLVALUE = U.objectFieldOffset

        (ck.getDeclaredField("value"));

    Class<?> ak = Node[].class;

    ABASE = U.arrayBaseOffset(ak);

    int scale = U.arrayIndexScale(ak);

    if ((scale & (scale - 1)) != 0)

        throw new Error("data type scale not a power of two");

    ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);

} catch (Exception e) {

    throw new Error(e);

}

}



#### []( https://gitee.com/vip204888/java-p7 )Three core methods



ConcurrentHashMap Three atomic operations are defined to operate on nodes at specified locations. It is these atomic operations that ensure ConcurrentHashMap Thread safe.



@SuppressWarnings("unchecked")

//Get the Node at i position

static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {

return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);

}



*   utilize CAS Algorithm settings i In position Node Node. Concurrency can be achieved because it specifies the value of the original node

*   stay CAS In the algorithm, it will compare whether the value in memory is equal to the value you specify. If it is equal, it will accept your modification, otherwise it will reject your modification

*   Therefore, the value in the current thread is not the latest value. This modification may overwrite the modification results of other threads, which is somewhat similar to SVN



static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,

                                Node<K,V> c, Node<K,V> v) {

return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);

}

//Use the volatile method to set the value of the node location

static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {

U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);

}



[](https://gitee.com/vip204888/java-p7) initialization method initTable

---------------------------------------------------------------------------------



*   about ConcurrentHashMap Generally speaking, calling its constructor is just setting some parameters.

*   whole table The initialization of is to ConcurrentHashMap Occurs when an element is inserted into the.

    *   Such as call put,computeIfAbsent,compute,merge When waiting for a method, the call time is to check table==null. 



1.  The initialization method mainly applies the key attributes sizeCtl If this value <0,Indicates that other threads are initializing, so this operation is abandoned.

2.  It can also be seen here ConcurrentHashMap Initialization of can only be completed by one thread.

3.  If you get initialization permission, use CAS Method will sizeCtl Set as-1,Prevent other threads from entering.



After initializing the array, the sizeCtl Change the value of to 0.75 \* n,The source code is as follows:



/**

  • Initializes table, using the size recorded in sizeCtl.

*/

private final Node<K,V>[] initTable() {

Node<K,V>[] tab; int sc;

while ((tab = table) == null || tab.length == 0) {

		//sizeCtl indicates that another thread is initializing and suspending the thread. For the initialization of table, only one thread can be in progress.

    if ((sc = sizeCtl) < 0)

        Thread.yield(); // lost initialization race; just spin

    else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {//Use CAS method to set the value of sizectl to - 1, indicating that this thread is initializing

        try {

            if ((tab = table) == null || tab.length == 0) {

                int n = (sc > 0) ? sc : DEFAULT_CAPACITY;

                @SuppressWarnings("unchecked")

                Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];

                table = tab = nt;

                sc = n - (n >>> 2);//It is equivalent to 0.75*n. set a capacity expansion threshold

            }

        } finally {

            sizeCtl = sc;

        }

        break;

    }

}

return tab;

}



### []( https://gitee.com/vip204888/java-p7 )Capacity expansion method transfer



*   ConcurrentHashMap When the capacity is insufficient, it is necessary to table Capacity expansion.

*   The basic idea of this method is similar to HashMap It is very similar, but it is much more complex because it supports concurrent capacity expansion.

*   The reason is that it supports multi-threaded capacity expansion without locking.

*   I think the purpose of this is not just to meet concurrent Instead, we hope to use concurrent processing to reduce the time impact of capacity expansion. Because the operation of copying from one "array" to another "array" is always involved in capacity expansion. If this operation can be carried out concurrently, it is really excellent.



#### []( https://gitee.com/vip204888/java-p7 )The whole capacity expansion operation is divided into two parts



*   The first part is to build a nextTable,Its capacity is twice that of the original, and this operation is completed by a single thread. This single thread guarantee is through`RESIZE_STAMP_SHIFT`This constant is guaranteed by one operation, which will be mentioned later;

*   **The second part is to table Copy elements from to nextTable In, multithreading is allowed**. 



#### []( https://gitee.com/vip204888/java-p7 )Let's take a look at how a single thread is completed:



*   Its general idea is the process of traversal and replication. Firstly, the number of times to traverse is obtained according to the operation i,Then use tabAt Method obtain i Elements of location:

*   If this position is empty, it is in**primary table**Medium i Position put**forwardNode node**,So is this**Key points to trigger concurrent capacity expansion**;

*   If this position is Node Node( fh>=0),**If it is the head node of a linked list, a reverse linked list is constructed**,Put them separately nextTable of i and i+n On the location of

*   **If this position is TreeBin Node( fh<0),Also do a reverse order processing and judge whether it is necessary untreefi,Put the processing results separately nextTable of i and i+n On the location of**

*   **After traversing all the nodes, the replication is completed. At this time, let nextTable As new table,And update sizeCtl 0 for new capacity.75 Times to complete capacity expansion**. 



#### []( https://gitee.com/vip204888/java-p7 )Let's take another look at how multithreading is accomplished:



*   If the traversed node is forward The node continues to traverse backward, and the mechanism of locking the node completes the control of multithreading.

*   Multithreading traverses a node, processes a node, and puts the value of the corresponding point set by forward,Another thread sees forward,Just traverse backwards.

*   This completes the replication. It also solves the problem of thread safety. The design of this method really makes me worship.



![img](https://img-blog.csdnimg.cn/img_convert/4c6dcc27cab4a76ef0abfa4f1f4b7671.png)



/**

  • A transitional table can only be used during capacity expansion

*/

private transient volatile Node<K,V>[] nextTable;

/**

  • Moves and/or copies the nodes in each bin to new table. See

  • above for explanation.

*/

private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {

int n = tab.length, stride;

if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)

    stride = MIN_TRANSFER_STRIDE; // subdivide range

if (nextTab == null) {            // initiating

    try {

        @SuppressWarnings("unchecked")

        Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];//Construct a nextTable object with twice the original capacity

        nextTab = nt;

    } catch (Throwable ex) {      // try to cope with OOME

        sizeCtl = Integer.MAX_VALUE;

        return;

    }

    nextTable = nextTab;

    transferIndex = n;

}

int nextn = nextTab.length;

ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);//Construct a connected node pointer for flag bit

boolean advance = true;//If the key attribute of concurrent capacity expansion is equal to true, it indicates that this node has been processed

boolean finishing = false; // to ensure sweep before committing nextTab

for (int i = 0, bound = 0;;) {

    Node<K,V> f; int fh;

    //The function of the while loop body is to control i -- through i -- to traverse the nodes in the original hash table in turn

    while (advance) {

        int nextIndex, nextBound;

        if (--i >= bound || finishing)

            advance = false;

        else if ((nextIndex = transferIndex) <= 0) {

            i = -1;

            advance = false;

        }

        else if (U.compareAndSwapInt

                 (this, TRANSFERINDEX, nextIndex,

                  nextBound = (nextIndex > stride ?

                               nextIndex - stride : 0))) {

            bound = nextBound;

            i = nextIndex - 1;

            advance = false;

        }

    }

    if (i < 0 || i >= n || i + n >= nextn) {

        int sc;

        if (finishing) {

        	//If all nodes have finished copying, assign nextTable to table and empty the temporary object nextTable

            nextTable = null;

            table = nextTab;

            sizeCtl = (n << 1) - (n >>> 1);//The capacity expansion threshold is set to 1.5 times the original capacity, which is still 0.75 times the current capacity

            return;

        }

        //The CAS method is used to update the capacity expansion threshold, where the sizectl value is reduced by one, indicating that a new thread is added to participate in the capacity expansion operation

        if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {

            if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)

                return;

            finishing = advance = true;

            i = n; // recheck before commit

        }

    }

    //If the traversed node is null, it is put into the ForwardingNode pointer

    else if ((f = tabAt(tab, i)) == null)

        advance = casTabAt(tab, i, null, fwd);

    //If you traverse the ForwardingNode node, it indicates that this point has been processed. Skip it directly. This is the core of controlling concurrent expansion

    else if ((fh = f.hash) == MOVED)

        advance = true; // already processed

    else {

    		//Node locking

        synchronized (f) {

            if (tabAt(tab, i) == f) {

                Node<K,V> ln, hn;

                //If FH > = 0, it proves that this is a Node node

                if (fh >= 0) {

                    int runBit = fh & n;

                    //The following work is to construct two linked lists. One is the original linked list, and the other is the reverse order of the original linked list

                    Node<K,V> lastRun = f;

                    for (Node<K,V> p = f.next; p != null; p = p.next) {

                        int b = p.hash & n;

                        if (b != runBit) {

                            runBit = b;

                            lastRun = p;

                        }

                    }

                    if (runBit == 0) {

                        ln = lastRun;

                        hn = null;

                    }

                    else {

                        hn = lastRun;

                        ln = null;

                    }

                    for (Node<K,V> p = f; p != lastRun; p = p.next) {

                        int ph = p.hash; K pk = p.key; V pv = p.val;

                        if ((ph & n) == 0)

                            ln = new Node<K,V>(ph, pk, pv, ln);

                        else

                            hn = new Node<K,V>(ph, pk, pv, hn);

                    }

                    //Insert a linked list at the i position of the nextTable

                    setTabAt(nextTab, i, ln);

                    //Insert another linked list at the i+n position of nextTable

                    setTabAt(nextTab, i + n, hn);

                    //Inserting a forwardNode node at the i position of the table indicates that the node has been processed

                    setTabAt(tab, i, fwd);

                    //Set advance to true and return to the while loop above to perform i-- operations

                    advance = true;

                }

                //Processing the TreeBin object is similar to the above procedure

                else if (f instanceof TreeBin) {

                    TreeBin<K,V> t = (TreeBin<K,V>)f;

                    TreeNode<K,V> lo = null, loTail = null;

                    TreeNode<K,V> hi = null, hiTail = null;

                    int lc = 0, hc = 0;

                    //Construct positive order and reverse order linked lists

                    for (Node<K,V> e = t.first; e != null; e = e.next) {

                        int h = e.hash;

                        TreeNode<K,V> p = new TreeNode<K,V>

                            (h, e.key, e.val, null, null);

                        if ((h & n) == 0) {

                            if ((p.prev = loTail) == null)

                                lo = p;

                            else

                                loTail.next = p;

                            loTail = p;

                            ++lc;

                        }

                        else {

                            if ((p.prev = hiTail) == null)

                                hi = p;

                            else

                                hiTail.next = p;

                            hiTail = p;

                            ++hc;

                        }

                    }

                    //If the tree structure is no longer needed after capacity expansion, it is inversely converted to a linked list structure

                    ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) :

                        (hc != 0) ? new TreeBin<K,V>(lo) : t;

                    hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) :

                        (lc != 0) ? new TreeBin<K,V>(hi) : t;

                     //Insert a linked list at the i position of the nextTable 

                    setTabAt(nextTab, i, ln);

                    //Insert another linked list at the i+n position of nextTable

                    setTabAt(nextTab, i + n, hn);

                     //Inserting a forwardNode node at the i position of the table indicates that the node has been processed

                    setTabAt(tab, i, fwd);

                    //Set advance to true and return to the while loop above to perform i-- operations

                    advance = true;

                }

            }

        }

    }

}

}



### []( https://gitee.com/vip204888/java-p7 )Put method



> ConcurrentHashMap The most commonly used is put and get Two methods



1.  according to hash Calculate the value of this newly inserted point table Location in i,If i If the position is empty, put it in directly, otherwise judge, if i The position is a tree node. Insert a new node in the way of a tree, otherwise i Insert to the end of the linked list.

2.  **ConcurrentHashMap One of the most important differences is that we still use this idea ConcurrentHashMap not allow key or value by null value**. 

    *   **In addition, since multithreading is involved, put The method is a little more complicated. There are two possible situations in multithreading**

3.  **If one or more threads are ConcurrentHashMap For capacity expansion, the current thread should also enter the capacity expansion operation**. 

    *   The reason why this expansion operation can be detected,**Because transfer Method is inserted on an empty node forward node**,If the position to be inserted is detected**forward**If the node is occupied, it helps to expand the capacity;

    *   **If it is detected that the node to be inserted is not empty and not empty forward Node, lock this node to ensure thread safety**. Although this has some impact on efficiency, it will be better than hashTable of synchronized Much better.

    *   **The overall process is to first define not allowed key or value by null For each placed value, first use spread Method pair key of hashcode Once hash Calculation to determine this value in table Location in**. 



If this position is empty, it can be placed directly without locking.



If there is a node at this location, it indicates that something has happened hash Collision, first judge the type of this node.



If it is a linked list node( fh>0),The resulting node is hash The head node of the linked list composed of nodes with the same value.



You need to traverse backward in turn to determine the location of the newly added value.



If encountered hash Value and key If the values are consistent with the newly added node, you only need to update value Value. Otherwise, traverse backward in turn until the end of the linked list is inserted into this node. If the length of the linked list after adding this node is greater than 8, the linked list will be converted into a red black tree. If the type of this node is already a tree node, directly call the insertion method of the tree node to insert a new value.



public V put(K key, V value) {

return putVal(key, value, false);

}

/** Implementation for put and putIfAbsent */

final V putVal(K key, V value, boolean onlyIfAbsent) {

	//null key or value is not allowed

if (key == null || value == null) throw new NullPointerException();

//Calculate hash value

int hash = spread(key.hashCode());

int binCount = 0;

//When does the loop insert successfully and jump out

for (Node<K,V>[] tab = table;;) {

    Node<K,V> f; int n, i, fh;

    //If the table is empty, initialize the table

    if (tab == null || (n = tab.length) == 0)

        tab = initTable();

    //Calculate the position in the table according to the hash value 

    else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {

    	//If this position has no value, put it directly without locking

        if (casTabAt(tab, i, null,

                     new Node<K,V>(hash, key, value, null)))

            break;                   // no lock when adding to empty bin

    }

    //When a table join point is encountered, you need to consolidate the table

    else if ((fh = f.hash) == MOVED)

        tab = helpTransfer(tab, f);

    else {

        V oldVal = null;

        //The node here can be understood as the head node of the linked list with the same hash value

        synchronized (f) {

            if (tabAt(tab, i) == f) {

                //fh > 0 indicates that this node is a linked list node, not a tree node

                if (fh >= 0) {

                    binCount = 1;

                    //Traverse all nodes of the linked list here

                    for (Node<K,V> e = f;; ++binCount) {

                        K ek;

                        //If the hash value and the key value are the same, modify the value value of the corresponding node

                        if (e.hash == hash &&

                            ((ek = e.key) == key ||

                             (ek != null && key.equals(ek)))) {

                            oldVal = e.val;

                            if (!onlyIfAbsent)

                                e.val = value;

                            break;

                        }

                        Node<K,V> pred = e;

                        //If you traverse to the last node, it proves that the new node needs to be inserted, so you insert it at the end of the linked list

                        if ((e = e.next) == null) {

                            pred.next = new Node<K,V>(hash, key,

                                                      value, null);

                            break;

                        }

                    }

                }

                //If the node is a tree node, the value is inserted in the form of a tree

                else if (f instanceof TreeBin) {

                    Node<K,V> p;

                    binCount = 2;

                    if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,

                                                   value)) != null) {

                        oldVal = p.val;

                        if (!onlyIfAbsent)

                            p.val = value;

                    }

                }

            }

        }

        if (binCount != 0) {

        	//If the length of the linked list has reached the critical value 8, you need to convert the linked list into a tree structure

            if (binCount >= TREEIFY_THRESHOLD)

                treeifyBin(tab, i);

            if (oldVal != null)

                return oldVal;

            break;

        }

    }

}

//Add the number of elements of the current ConcurrentHashMap + 1

addCount(1L, binCount);

return null;

}



### []( https://gitee.com/vip204888/java-p7 )Helptransfer method



This is a method to assist in capacity expansion. When this method is called, the current ConcurrentHashMap There must be already nextTable Object, get this first nextTable Object, calling transfer method. Look back at the above transfer Method can be seen that when this thread enters the capacity expansion method, it will directly enter the replication phase.



/**

  • Helps transfer if a resize is in progress.

*/

final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {

Node<K,V>[] nextTab; int sc;

if (tab != null && (f instanceof ForwardingNode) &&

    (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {

    int rs = resizeStamp(tab.length);//Calculate an operation check code

    while (nextTab == nextTable && table == tab &&

           (sc = sizeCtl) < 0) {

        if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||

summary

Generally, large enterprises like this have several rounds of interviews, so they must take some time to collect and sort out the company's background and corporate culture. As the saying goes, "know yourself and know the enemy. You will never be defeated in a hundred battles". Don't go to the interview blindly. Many people are concerned about how to talk about salary with HR.

Here's a suggestion. If your ideal salary is 30K, you can talk to HR about 33~35K instead of exposing your cards at once. However, you can't say it so directly. For example, your company was 25K. You can tell HR about the original salary and what you can give me? You said I hope to have a 20% salary increase.

Finally, say a few more words about the recruitment platform. In short, before submitting your resume to the company, please confirm what the company is like. Go to Baidu first. Don't be trapped. There are some ill intentioned advertising parties waiting for you on each platform. Don't be fooled!!!

Provide [free] Java architecture learning materials, including: Spring, Dubbo, MyBatis, RPC, source code analysis, high concurrency, high performance, distributed, performance optimization, advanced architecture development of microservices, etc.

A full set of advanced Java data points are available here for free

There are also Java core knowledge points + a full range of architects' learning materials and videos + a big factory interview Treasure + interview template, you can receive + Ali, NetEase, Tencent, Iqiyi, Kwai, Iqiyi, beep, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li Yuan, +Spring, the source code of the interview, and the book is about the real e-book of the Java structure.
if a resize is in progress.

*/

final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {

Node<K,V>[] nextTab; int sc;

if (tab != null && (f instanceof ForwardingNode) &&

    (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {

    int rs = resizeStamp(tab.length);//Calculate an operation check code

    while (nextTab == nextTable && table == tab &&

           (sc = sizeCtl) < 0) {

        if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||

summary

Generally, large enterprises like this have several rounds of interviews, so they must take some time to collect and sort out the company's background and corporate culture. As the saying goes, "know yourself and know the enemy. You will never be defeated in a hundred battles". Don't go to the interview blindly. Many people are concerned about how to talk about salary with HR.

Here's a suggestion. If your ideal salary is 30K, you can talk to HR about 33~35K instead of exposing your cards at once. However, you can't say it so directly. For example, your company was 25K. You can tell HR about the original salary and what you can give me? You said I hope to have a 20% salary increase.

Finally, say a few more words about the recruitment platform. In short, before submitting your resume to the company, please confirm what the company is like. Go to Baidu first. Don't be trapped. There are some ill intentioned advertising parties waiting for you on each platform. Don't be fooled!!!

Provide [free] Java architecture learning materials, including: Spring, Dubbo, MyBatis, RPC, source code analysis, high concurrency, high performance, distributed, performance optimization, advanced architecture development of microservices, etc.

A full set of advanced Java data points are available here for free

There are also Java core knowledge points + a full range of architects' learning materials and videos + a big factory interview Treasure + interview template, you can receive + Ali, NetEase, Tencent, Iqiyi, Kwai, Iqiyi, beep, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li, Li Yuan, +Spring, the source code of the interview, and the book is about the real e-book of the Java structure.

Topics: Java Back-end Interview Programmer