Implementation of ThreadLocalMap to resolve Hash conflicts in Java
ThreadLocalMap
The main way to resolve hash conflicts is to use linear probing. This method uses linear probing to find empty slots to deal with hash conflicts. Here are the detailed solutions:
1. Linear detection method
When a hash collision occurs, the linear detection method finds an empty slot by checking the next position in the array. If the current slot has been occupied, it will continue to check the next slot until a blank slot or a suitable slot is found.
2. Hash conflict resolution in ThreadLocalMap implementation
ThreadLocalMap
Handle hash conflicts through the following methods:
-
Calculate index:
- use
ThreadLocal
The hash code to calculate inEntry
Index in array. - The index is
ThreadLocal
ExamplethreadLocalHashCode
and array length (minus 1) are obtained by bitwise operation.
- use
-
Linear detection:
- If the calculated index position has been occupied (that is, there is already
Entry
Object),ThreadLocalMap
The next position in the array will be checked by linear detection until a empty slot or a suitable slot is found. - use
nextIndex
Method to implement linear detection, which increases the current position by 1 and loops back to the beginning of the array.
- If the calculated index position has been occupied (that is, there is already
-
Processing outdated entries:
- If you encounter it during the detection process
Entry
The key ofnull
(i.e. outdated entries),ThreadLocalMap
Will callexpungeStaleEntry
Method to clean up these outdated entries and insert the current entries into the appropriate location.
- If you encounter it during the detection process
Key code analysis
The following isThreadLocalMap
Related code for handling hash conflicts:
static class ThreadLocalMap { // Array of entries stored private Entry[] table; // Number of entries stored private int size = 0; // Define the initial capacity private static final int INITIAL_CAPACITY = 16; // Constructor ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; } // Linear detection method to obtain Entry private Entry getEntry(ThreadLocal<?> key) { int i = & ( - 1); Entry e = table[i]; if (e != null && () == key) return e; else return getEntryAfterMiss(key, i, e); } // Post-processing of linear detection method private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) { Entry[] tab = table; int len = ; while (e != null) { ThreadLocal<?> k = (); if (k == key) return e; if (k == null) expungeStaleEntry(i); else i = nextIndex(i, len); e = tab[i]; } return null; } // Set value private void set(ThreadLocal<?> key, Object value) { Entry[] tab = table; int len = ; int i = & (len - 1); for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = (); if (k == key) { = value; return; } if (k == null) { replaceStaleEntry(key, value, i); return; } } tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); } // Get the next index private int nextIndex(int i, int len) { return ((i + 1 < len) ? i + 1 : 0); } // Replace obsolete entries private void replaceStaleEntry(ThreadLocal<?> key, Object value, int staleSlot) { Entry[] tab = table; int len = ; Entry e; int slotToExpunge = staleSlot; for (int i = prevIndex(staleSlot, len); (e = tab[i]) != null; i = prevIndex(i, len)) { if (() == null) slotToExpunge = i; } for (int i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) { ThreadLocal<?> k = (); if (k == key) { = value; tab[i] = tab[staleSlot]; tab[staleSlot] = e; if (slotToExpunge == staleSlot) slotToExpunge = i; cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); return; } if (k == null && slotToExpunge == staleSlot) slotToExpunge = i; } tab[staleSlot].value = null; tab[staleSlot] = new Entry(key, value); if (slotToExpunge != staleSlot) cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); } // Process outdated entries private int expungeStaleEntry(int staleSlot) { Entry[] tab = table; int len = ; tab[staleSlot].value = null; tab[staleSlot] = null; size--; Entry e; int i; for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) { if (() == null) { = null; tab[i] = null; size--; } else { int h = ().threadLocalHashCode & (len - 1); if (h != i) { tab[i] = null; while (tab[h] != null) h = nextIndex(h, len); tab[h] = e; } } } return i; } // Clean some slots private boolean cleanSomeSlots(int i, int n) { boolean removed = false; Entry[] tab = table; int len = ; do { i = nextIndex(i, len); Entry e = tab[i]; if (e != null && () == null) { n = len; removed = true; i = expungeStaleEntry(i); } } while ((n >>>= 1) != 0); return removed; } // Rehash private void rehash() { expungeStaleEntries(); if (size >= threshold - threshold / 4) resize(); } private void expungeStaleEntries() { Entry[] tab = table; int len = ; for (int j = 0; j < len; j++) { Entry e = tab[j]; if (e != null && () == null) expungeStaleEntry(j); } } private void resize() { Entry[] oldTab = table; int oldLen = ; int newLen = oldLen * 2; Entry[] newTab = new Entry[newLen]; int count = 0; for (int j = 0; j < oldLen; ++j) { Entry e = oldTab[j]; if (e != null) { ThreadLocal<?> k = (); if (k == null) { = null; } else { int h = & (newLen - 1); while (newTab[h] != null) h = nextIndex(h, newLen); newTab[h] = e; count++; } } } setThreshold(newLen); size = count; table = newTab; } }
Important details
-
Calculate index:
-
i = & (len - 1);
useThreadLocal
The hash code and table length minus 1 bitwise operation to calculate the index.
-
-
Linear detection:
-
nextIndex(i, len)
Method calculates the next index position and is used to detect conflicts. - If there is a conflict, it will be
table
Continue searching in the array until the empty slot is found.
-
-
Clean up and rehash:
- use
expungeStaleEntry
Method to clean outdated entries. -
resize()
Methods extend the array and reassign entries to reduce conflicts and improve performance.
- use
Summarize
ThreadLocalMap
Use linear detection method to resolve hash conflicts
This is the article about the implementation of ThreadLocalMap in Java to resolve Hash conflicts. For more related threadlocalmap to resolve hash conflicts, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!
Related Articles
How to implement full-width and half-width character conversion in java
You may have used the full-width and half-width character conversion problem in Java, so I searched and sorted it out and shared it with you. I hope it can help you2012-12-12Explain what Spring Bean is in detail (example explanation)
Spring Bean is an object instance managed by the Spring IoC container and is also one of the basic components of the Spring framework. This article introduces the relevant usage methods of Spring Bean’s scope (Bean Scope) through sample code. Interested friends can take a look.2023-09-09Java manipulates GraphQL through API
This article mainly introduces Java to operate GraphQL through API, helping everyone better understand and learn to use Java. Interested friends can learn about it.2021-05-05Detailed explanation of the repeated DNA sequences of Go Java algorithm
This article mainly introduces a detailed explanation of the repetitive DNA sequences of Go Java algorithm. Friends in need can refer to it for reference. I hope it can be helpful. I wish you more progress and get promoted as soon as possible to get a salary increase as soon as possible.2022-08-08Detailed explanation of the use of special symbols in the xml file of Mybatis or Mybatis-Plus framework
This article mainly introduces the detailed explanation of the use of special symbols in the xml file of Mybatis or Mybatis-Plus framework. The article introduces the example code in detail, which has certain reference learning value for everyone's study or work. Friends who need it, please learn with the editor below.2020-11-11The difference between -D, -X, -XX parameters in JVM
This article mainly introduces the differences between -D, -X, and -XX parameters in JVM. The example code is introduced in this article in detail, which has certain reference learning value for everyone's learning or work. Friends who need it, please learn with the editor below.2023-06-06About the issue of getting and changing current user information in SpringSecurity Context
SpringSecurityContext cannot obtain user information in asynchronous threads because it is bound to the request thread; in addition, when the user information is updated and jumps to the page, the identity will be downgraded to anonymous, resulting in the information being unable to be synchronized in time. This article introduces the issue of obtaining and changing the current user information in SpringSecurity Context. Interested friends, let’s take a look.2024-09-09selenium-java implements automatic login and jump page
Using Selenium and Java languages, you can write a script to automatically refresh the web page. First of all, you need to ensure that the versions of Google browser and Chrome-Driver driver are consistent. By specifying the website to download the corresponding version of the browser and driver, add dependencies in the Maven project, and write scripts to achieve automatic refresh of the web page. This method is suitable for scenarios where frequent refresh of the web pages is required, simplifying operations and improving efficiency.2024-11-11springboot-2. The latest version of source code reading environment construction (built based on gradle)
This article mainly introduces the latest version of the source code reading environment construction (built based on gradle). Friends who need it can refer to it.2020-08-08How to open CSV file in Java to JTable display
This article mainly introduces how to open CSV files in Java to JTable to display. The article introduces the example code in detail, which has certain reference learning value for everyone's study or work. Friends who need it, please learn with the editor below.2023-03-03