当前位置:网站首页>What the hell is fastthreadlocal? The existence of ThreadLocal!!

What the hell is fastthreadlocal? The existence of ThreadLocal!!

2020-11-06 21:09:00 Java technology stack

ThreadLocal We all know it's a thread local variable , Today, the storekeeper introduces another artifact :FastThreadLocal, Literally :Fast + ThreadLocal, A quick one ThreadLocal? What the hell is this ?

One 、FastThreadLocal brief introduction

FastThreadLocal Not at all JDK Self contained , But in Netty A wheel made in China ,Netty Why make wheels over and over again ?

Take a look at the annotation definition in its source code :

/**
 * A special variant of {@link ThreadLocal} that yields higher access performance when accessed from a
 * {@link FastThreadLocalThread}.
 * <p>
 * Internally, a {@link FastThreadLocal} uses a constant index in an array, instead of using hash code and hash table,
 * to look for a variable.  Although seemingly very subtle, it yields slight performance advantage over using a hash
 * table, and it is useful when accessed frequently.
 * </p><p>
 * To take advantage of this thread-local variable, your thread must be a {@link FastThreadLocalThread} or its subtype.
 * By default, all threads created by {@link DefaultThreadFactory} are {@link FastThreadLocalThread} due to this reason.
 * </p><p>
 * Note that the fast path is only possible on threads that extend {@link FastThreadLocalThread}, because it requires
 * a special field to store the necessary state.  An access by any other kind of thread falls back to a regular
 * {@link ThreadLocal}.
 * </p>
 *
 * @param <V> the type of the thread-local variable
 * @see ThreadLocal
 */
public class FastThreadLocal<V> {
	...
}

FastThreadLocal It's a special one ThreadLocal variant , When from thread class FastThreadLocalThread Medium visit FastThreadLocalm Can get higher access performance . If you don't know what is ThreadLocal, You can pay attention to the official account. Java Technology stack read the article I shared earlier .

Two 、FastThreadLocal Why fast ?

stay FastThreadLocal Inside , Index constants are used instead of Hash Code Hash table , The source code is as follows :

private final int index;

public FastThreadLocal() {
    index = InternalThreadLocalMap.nextVariableIndex();
}
public static int nextVariableIndex() {
    int index = nextIndex.getAndIncrement();
    if (index < 0) {
        nextIndex.decrementAndGet();
        throw new IllegalStateException("too many thread-local indexed variables");
    }
    return index;
}

FastThreadLocal An index constant is maintained internally index, This constant is created each time FastThreadLocal Zhongdu will automatically +1, Thus, the non repetition of subscripts is ensured .

This has to be done, although it will produce a lot of index, But it avoided being in the ThreadLocal Index subscript position calculation and processing in hash Loss caused by conflict , Therefore, the use of fixed subscripts in the operation of arrays has certain performance advantages over the use of computed hash subscripts , Especially when it is used frequently , Trade space for time , That's high performance Netty The subtlety of .

Use FastThreadLocal Performance advantages , It must be used in combination FastThreadLocalThread Thread class or its subclass , because FastThreadLocalThread The thread class stores the necessary state , If you use non FastThreadLocalThread The thread class goes back to normal ThreadLocal.

Netty Provides inheritance classes and thread classes that implement interfaces :

  • FastThreadLocalRunnable
  • FastThreadLocalThread

Netty Also provided DefaultThreadFactory Factory , All by DefaultThreadFactory The default thread created by the factory class is FastThreadLocalThread type , Take a look at how it was created :

First create FastThreadLocalRunnable, To create a FastThreadLocalThread, Match with friends , Work is not tiring , It must be used together “ fast ”.

3、 ... and 、FastThreadLocal actual combat

To use FastThreadLocal You need to import Netty Rely on the :

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.52.Final</version>
</dependency>

Write a test sample :

import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.FastThreadLocal;

public class FastThreadLocalTest {

    public static final int MAX = 100000;

    public static void main(String[] args) {
        new Thread(() -> threadLocal()).start();
        new Thread(() -> fastThreadLocal()).start();
    }

    private static void fastThreadLocal() {
        long start = System.currentTimeMillis();
        DefaultThreadFactory defaultThreadFactory = new DefaultThreadFactory(FastThreadLocalTest.class);

        FastThreadLocal<String>[] fastThreadLocal = new FastThreadLocal[MAX];

        for (int i = 0; i < MAX; i++) {
            fastThreadLocal[i] = new FastThreadLocal<>();
        }

        Thread thread = defaultThreadFactory.newThread(() -> {
            for (int i = 0; i < MAX; i++) {
                fastThreadLocal[i].set("java: " + i);
            }

            System.out.println("fastThreadLocal set: " + (System.currentTimeMillis() - start));

            for (int i = 0; i < MAX; i++) {
                for (int j = 0; j < MAX; j++) {
                    fastThreadLocal[i].get();
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("fastThreadLocal total: " + (System.currentTimeMillis() - start));
    }

    private static void threadLocal() {
        long start = System.currentTimeMillis();
        ThreadLocal<String>[] threadLocals = new ThreadLocal[MAX];

        for (int i = 0; i < MAX; i++) {
            threadLocals[i] = new ThreadLocal<>();
        }

        Thread thread = new Thread(() -> {
            for (int i = 0; i < MAX; i++) {
                threadLocals[i].set("java: " + i);
            }

            System.out.println("threadLocal set: " + (System.currentTimeMillis() - start));

            for (int i = 0; i < MAX; i++) {
                for (int j = 0; j < MAX; j++) {
                    threadLocals[i].get();
                }
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("threadLocal total: " + (System.currentTimeMillis() - start));
    }

}

Results output :

It can be seen that , In front of a lot of reading and writing , The efficiency of the write operation is about the same , But read operations FastThreadLocal Than ThreadLocal Fast is not an order of magnitude , It's a second kill ThreadLocal The existence of .

When I put MAX Value to 1000 when , Results output :

When there are few read and write operations ,ThreadLocal Obviously better !

The example above is a single thread testing multiple *ThreadLocal, That is, array form , in addition , I also tested multithreading single *ThreadLocal, Now FastThreadLocal Efficiency will obviously lag behind ThreadLocal..

The last thing to say is , After use FastThreadLocal Not after that remove 了 , Because in FastThreadLocalRunnable Remove logic has been added to , All variables bound to the current thread are removed when the thread runs out .

therefore , Use FastThreadLocal Will the probability of memory overflow be lower than ThreadLocal?

not always , because FastThreadLocal A lot of index Constant , The so-called space for time , So feel FastThreadLocal The probability of memory overflow is higher , But the good news is that every time you use it, it will automatically remove.

Four 、 summary

Netty Medium FastThreadLocal In a large number of frequent read and write operations, the efficiency is higher than ThreadLocal, But we should pay attention to the combination Netty Self contained thread class , This could be Netty Why one of the mysteries of high performance !

If there is not a large number of frequent read and write operations ,JDK Self contained ThreadLocal sufficient , And the performance is better than that FastThreadLocal.

Okay , Today's sharing is here , Feel useful , Forward to share .

Last ,Java The series will continue to be updated , Focus on Java Technology stack official account for the first time push , You can also get history from the official account menu. Java course , Is dry .

Copyright notice : The official account is No. "Java Technology stack " original , It's not easy to be original , Reprint 、 Please indicate the source of this article , No plagiarism 、 Manuscript preparation , Please take care of yourself , Respect other people's labor achievements and intellectual property rights .

Recent hot article recommends :

1.Java 15 Official release , 14 A new feature , Refresh your mind !!

2. Finally, I got it through open source projects IntelliJ IDEA Activation code , It's delicious !

3. I use Java 8 Wrote a piece of logic , I can't understand it , You try ..

4. To hang up Tomcat ,Undertow It's very powerful !!

5.《Java Development Manual ( Song Mountain version )》 The latest release , Download it quickly !

I think it's good , Don't forget to like it + Forward !

版权声明
本文为[Java technology stack]所创,转载请带上原文链接,感谢