Suche…


Bemerkungen

Am besten für Objekte SimpleDateFormat , die beim Aufruf eines Anrufs auf Interna angewiesen sind, ansonsten aber staatenlos sind, wie SimpleDateFormat , Marshaller

Bei der Verwendung von Random ThreadLocal sollten Sie ThreadLocalRandom

ThreadLocal Java 8-Funktionsinitialisierung

public static class ThreadLocalExample
{
    private static final ThreadLocal<SimpleDateFormat> format = 
        ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd_HHmm"));

    public String formatDate(Date date)
    {
        return format.get().format(date);
    }
}

Grundlegende ThreadLocal-Verwendung

Java ThreadLocal wird verwendet, um lokale Thread-Variablen zu erstellen. Es ist bekannt, dass Threads eines Objekts seine Variablen gemeinsam nutzen, sodass die Variable nicht threadsicher ist. Wir können die Synchronisierung für die Thread-Sicherheit verwenden, aber wenn wir die Synchronisation vermeiden möchten, können Sie mit ThreadLocal lokale Variablen für den Thread erstellen, dh, nur dieser Thread kann diese Variablen lesen oder schreiben, sodass die anderen Threads denselben Code ausführen kann nicht auf die ThreadLocal-Variablen zugreifen.

Dies kann verwendet werden, um ThreadLocal Variablen zu verwenden. in Situationen, in denen Sie einen Thread-Pool haben, wie zum Beispiel in einem Webdienst. Das Erstellen eines SimpleDateFormat Objekts für jede Anforderung ist beispielsweise sehr zeitaufwändig, und ein statisches Objekt kann nicht erstellt werden, da SimpleDateFormat nicht SimpleDateFormat ist. SimpleDateFormat können wir ein ThreadLocal erstellen, sodass Thread-sichere Vorgänge ausgeführt werden können, ohne dass SimpleDateFormat muss Zeit.

Der folgende Code zeigt, wie er verwendet werden kann:

Jeder Thread hat seine eigene ThreadLocal Variable. Mit den Methoden get() und set() können sie den Standardwert abrufen oder den lokalen Wert in Thread ändern.

ThreadLocal Instanzen sind normalerweise private statische Felder in Klassen, die einem Thread den ThreadLocal möchten.

Hier ein kleines Beispiel, das die Verwendung von ThreadLocal im Java-Programm zeigt und beweist, dass jeder Thread eine eigene Kopie der ThreadLocal Variablen hat.

package com.examples.threads;

import java.text.SimpleDateFormat;
import java.util.Random;

public class ThreadLocalExample implements Runnable{

    // SimpleDateFormat is not thread-safe, so give one to each thread
 // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };
    
    public static void main(String[] args) throws InterruptedException {
        ThreadLocalExample obj = new ThreadLocalExample();
        for(int i=0 ; i<10; i++){
            Thread t = new Thread(obj, ""+i);
            Thread.sleep(new Random().nextInt(1000));
            t.start();
        }
    }

    @Override
    public void run() {
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
        try {
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        formatter.set(new SimpleDateFormat());
        
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
    }

}

Ausgabe:

Thread Name= 0 default Formatter = yyyyMMdd HHmm

Thread Name= 1 default Formatter = yyyyMMdd HHmm

Thread Name= 0 formatter = M/d/yy h:mm a

Thread Name= 2 default Formatter = yyyyMMdd HHmm

Thread Name= 1 formatter = M/d/yy h:mm a

Thread Name= 3 default Formatter = yyyyMMdd HHmm

Thread Name= 4 default Formatter = yyyyMMdd HHmm

Thread Name= 4 formatter = M/d/yy h:mm a

Thread Name= 5 default Formatter = yyyyMMdd HHmm

Thread Name= 2 formatter = M/d/yy h:mm a

Thread Name= 3 formatter = M/d/yy h:mm a

Thread Name= 6 default Formatter = yyyyMMdd HHmm

Thread Name= 5 formatter = M/d/yy h:mm a

Thread Name= 6 formatter = M/d/yy h:mm a

Thread Name= 7 default Formatter = yyyyMMdd HHmm

Thread Name= 8 default Formatter = yyyyMMdd HHmm

Thread Name= 8 formatter = M/d/yy h:mm a

Thread Name= 7 formatter = M/d/yy h:mm a

Thread Name= 9 default Formatter = yyyyMMdd HHmm

Thread Name= 9 formatter = M/d/yy h:mm a

Wie aus der Ausgabe hervorgeht, hat Thread-0 den Wert des Formatierers geändert, der Standardformatierer von Thread-2 ist jedoch mit dem initialisierten Wert identisch.

Mehrere Threads mit einem gemeinsamen Objekt

In diesem Beispiel haben wir nur ein Objekt, das jedoch von verschiedenen Threads gemeinsam genutzt wird. Eine normale Verwendung von Feldern zum Speichern des Zustands wäre nicht möglich, da der andere Thread dies auch sehen würde (oder wahrscheinlich nicht sehen würde).

public class Test {
    public static void main(String[] args) {
        Foo foo = new Foo();
        new Thread(foo, "Thread 1").start();
        new Thread(foo, "Thread 2").start();
    }
}

In Foo zählen wir von Null an. Anstatt den Status in einem Feld zu speichern, speichern wir unsere aktuelle Nummer im ThreadLocal-Objekt, das statisch zugänglich ist. Beachten Sie, dass die Synchronisierung in diesem Beispiel nicht mit der Verwendung von ThreadLocal zusammenhängt, sondern eine bessere Konsolenausgabe gewährleistet.

public class Foo implements Runnable {
    private static final int ITERATIONS = 10;
    private static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };

    @Override
    public void run() {
        for (int i = 0; i < ITERATIONS; i++) {
            synchronized (threadLocal) {
                //Although accessing a static field, we get our own (previously saved) value.
                int value = threadLocal.get();
                System.out.println(Thread.currentThread().getName() + ": " + value);
                
                //Update our own variable
                threadLocal.set(value + 1);

                try {
                    threadLocal.notifyAll();
                    if (i < ITERATIONS - 1) {
                        threadLocal.wait();
                    }
                } catch (InterruptedException ex) {
                }
            }
        }
    }
}

In der Ausgabe sehen wir, dass jeder Thread für sich selbst zählt und nicht den Wert des anderen verwendet:

Thread 1: 0
Thread 2: 0
Thread 1: 1
Thread 2: 1
Thread 1: 2
Thread 2: 2
Thread 1: 3
Thread 2: 3
Thread 1: 4
Thread 2: 4
Thread 1: 5
Thread 2: 5
Thread 1: 6
Thread 2: 6
Thread 1: 7
Thread 2: 7
Thread 1: 8
Thread 2: 8
Thread 1: 9
Thread 2: 9


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow