Heim  >  Artikel  >  Java  >  Detaillierte Einführung in ThreadLocal in Java (Codebeispiel)

Detaillierte Einführung in ThreadLocal in Java (Codebeispiel)

不言
不言nach vorne
2019-03-06 15:56:283308Durchsuche

Der Inhalt dieses Artikels ist eine detaillierte Einführung (Codebeispiel) über ThreadLocal in Java. Ich hoffe, dass er für Freunde hilfreich ist.

ThreadLocal wird grundsätzlich nicht in der Projektentwicklung verwendet, aber Interviewer ziehen es vor, diese Art von Fragen zu stellen, daher ist es dennoch notwendig, die Funktionen und Prinzipien dieser Art zu verstehen.

Was ist ThreadLocal

ThreadLocal ist eine Klasse, die für jeden Thread in Multi-Threads eine separate Kopie von Variablen erstellt. Wenn ThreadLocal zum Verwalten von Variablen verwendet wird, erstellt ThreadLocal für jeden Thread eine separate Kopie von Variablen, um durch Multi-Threads verursachte Dateninkonsistenzen zu vermeiden -Thread-Betrieb von gemeinsam genutzten Variablen;

In welchen Szenarien wird die ThreadLocal-Klasse verwendet?

Im Allgemeinen ist ThreadLocal in der tatsächlichen industriellen Produktion nicht üblich, wird aber in vielen Frameworks verwendet kann aber einige Framework-Probleme lösen; zum Beispiel werden Transaktionen in Spring und Scope Scope in Spring durch die Verwendung von ThreadLocal für Request的Bean

ThreadLocal-Verwendungsmethode

1 gelöst Um Attribute zu definieren, auf die mehrere Threads zugreifen müssen, nehmen Sie als Beispiel die DBConnectionFactory-Klasse, die im Internet am häufigsten verwendet wird.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnectionFactory {

    private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() {
        @Override
        protected Connection initialValue() {
            try {
                return DriverManager.getConnection("", "", "");
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    public Connection getConnection() {
        return dbConnectionLocal.get();
    }
}
Auf diese Weise wird die Verbindung von jedem erhalten, wenn der Client die Verbindung erhält Thread ist einzigartig für diesen Thread, er erreicht die Thread-Isolation von Connection; es gibt also kein Thread-Sicherheitsproblem.

Wie ThreadLocal die Thread-Isolation implementiert

1. Es verwendet hauptsächlich einen ThreadLocalMap-Typ im Thread-Objekt Die Variable threadLocals ist für die Speicherung des Connection-Objekts des aktuellen Threads verantwortlich. Die Variable dbConnectionLocal wird als Schlüssel verwendet, und in diesem Fall wird das neu erstellte Connection-Objekt als Wert verwendet, wenn der Thread zum Zeitpunkt des Lesens nicht vorhanden ist Zum ersten Mal wird die initialValue-Methode von ThreadLocal aufgerufen. Erstellen Sie ein Verbindungsobjekt und geben Sie Folgendes zurück:

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}
Zuerst Holen Sie sich das aktuelle Thread-Objekt t und dann die Mitglieder von ThreadLocalMap aus Thread t Attribut threadLocals

2. Wenn die threadLocals des aktuellen Threads initialisiert wurden (d. h. nicht null) und ein Wert vorhanden ist das aktuelle ThreadLocal-Objekt als Schlüssel und geben Sie dann direkt das vom aktuellen Thread abzurufende Objekt zurück (in diesem Beispiel die Verbindung). ;

3. Wenn die threadLocals des aktuellen Threads initialisiert wurden (d. h. nicht). null), aber es gibt kein Objekt mit dem aktuellen ThreadLocal-Objekt als Schlüssel. Erstellen Sie dann ein Verbindungsobjekt neu, fügen Sie es zur threadLocals-Map des aktuellen Threads hinzu und geben Sie

zurück. 4. Wenn das threadLocals-Attribut Wenn der aktuelle Thread nicht initialisiert wurde, erstellen Sie ein ThreadLocalMap-Objekt neu, erstellen Sie ein Connection-Objekt, fügen Sie es dem ThreadLocalMap-Objekt hinzu und kehren Sie zurück.

Wenn es existiert, wird es direkt zurückgegeben. Was ist also der Code für die Initialisierung?

private T setInitialValue() {
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}
1. Rufen Sie zuerst die überladene initialValue-Methode auf oben, um ein Verbindungsobjekt zu generieren

2. Überprüfen Sie weiterhin, ob die threadLocals des aktuellen Threads leer sind. Wenn die ThreadLocalMap initialisiert wurde, fügen Sie das generierte Objekt direkt zur ThreadLocalMap hinzu. Erstellen Sie das Objekt und fügen Sie es hinzu. ;

Gleichzeitig stellt ThreadLocal auch eine Methode zum direkten Betrieb von threadLocals im Thread-Objekt bereit

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}
Auf diese Weise können wir initialValue auch nicht implementieren und fügen Sie die Initialisierungsarbeit in die getConnection-Methode von DBConnectionFactory ein:

public Connection getConnection() {
    Connection connection = dbConnectionLocal.get();
    if (connection == null) {
        try {
            connection = DriverManager.getConnection("", "", "");
            dbConnectionLocal.set(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return connection;
}
Nachdem wir den Code gelesen haben, verstehen wir klar, warum ThreadLocal tatsächlich eine Multithread-Isolierung von Variablen erreichen kann Cache den aktuellen Thread, und wenn er verwendet wird, wird er von diesem Thread zwischengespeichert. Rufen Sie ihn einfach vom threadLocals-Objekt ab, und der Schlüssel ist der aktuelle Thread

Natürlich, wenn Sie die Objekte in der Karte abrufen Im aktuellen Thread und beim Betrieb unter dem aktuellen Thread wird es definitiv keine Thread-Parallelitätsprobleme geben. Natürlich können Variablen verwendet werden. Threads sind isoliert;

Jetzt wissen wir, was ThreadLocal ist und wie man es verwendet Können wir ThreadLocal und seine grundlegenden Implementierungsprinzipien beenden? Tatsächlich gibt es noch eine andere Frage: Was ist ThreadLocalMap? , es ist eine Map, aber diese ThreadLocalMap unterscheidet sich ein wenig von der Map, die wir normalerweise sehen

1 Sie implementiert keine öffentlichen Methoden und at Meistens ein Standardkonstruktor, da diese ThreadLocalMap-Methode nur in der ThreadLocal-Klasse aufgerufen wird und eine statische innere Klasse ist

3 Die Entry-Implementierung von ThreadLocalMap erbt WeakReference>

4. Diese Methode verwendet nur ein Eintragsarray zum Speichern von Schlüssel und Wert; der Eintrag erfolgt nicht in Form einer verknüpften Liste. Stattdessen wird nur ein Eintrag in jedem Bucket platziert.

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in ThreadLocal in Java (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen