Recherche…


Remarques

Utilisé de préférence pour les objets qui dépendent des composants internes lors de l'appel d'un appel, mais qui sont sans état, comme SimpleDateFormat , Marshaller

Pour l'utilisation Random ThreadLocal, envisagez d'utiliser ThreadLocalRandom

Initialisation fonctionnelle de ThreadLocal Java 8

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);
    }
}

Utilisation de base de ThreadLocal

Java ThreadLocal est utilisé pour créer des variables locales de thread. Il est connu que les threads d'un objet partagent ses variables, la variable n'est donc pas thread-safe. Nous pouvons utiliser la synchronisation pour la sécurité des threads mais si nous voulons éviter la synchronisation, ThreadLocal nous permet de créer des variables locales au thread, c’est-à-dire que seul ce thread peut lire ou écrire sur ces variables. ne seront pas en mesure d'accéder aux variables ThreadLocal les uns des autres.

Cela peut être utilisé, nous pouvons utiliser des variables ThreadLocal . dans les situations où vous avez un pool de threads comme par exemple dans un service Web. Par exemple, Création d' un SimpleDateFormat objet chaque fois pour chaque demande prend du temps et statique ne peut pas être créé SimpleDateFormat est pas thread - safe, afin que nous puissions créer un ThreadLocal afin que nous puissions effectuer fil des opérations de sécurité sans les frais généraux de la création SimpleDateFormat chaque temps.

Le morceau de code ci-dessous montre comment il peut être utilisé:

Chaque thread a sa propre variable ThreadLocal et ils peuvent utiliser ses méthodes get() et set() pour obtenir la valeur par défaut ou changer sa valeur en Thread.

ThreadLocal instances ThreadLocal sont généralement des champs statiques privés dans les classes qui souhaitent associer l'état à un thread.

Voici un petit exemple montrant l'utilisation de ThreadLocal dans le programme Java et prouvant que chaque thread a sa propre copie de la variable ThreadLocal .

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());
    }

}

Sortie:

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

Comme nous pouvons le voir à la sortie, Thread-0 a changé la valeur du formateur, mais le formateur par défaut du thread-2 est toujours identique à la valeur initialisée.

Plusieurs threads avec un objet partagé

Dans cet exemple, nous avons un seul objet mais il est partagé entre / exécuté sur différents threads. L'utilisation ordinaire des champs pour enregistrer l'état ne serait pas possible car l'autre thread verrait cela aussi (ou probablement pas voir).

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();
    }
}

Dans Foo nous comptons à partir de zéro. Au lieu de sauvegarder l'état dans un champ, nous stockons notre numéro actuel dans l'objet ThreadLocal qui est accessible statiquement. Notez que la synchronisation dans cet exemple n'est pas liée à l'utilisation de ThreadLocal mais garantit plutôt une meilleure sortie de la console.

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) {
                }
            }
        }
    }
}

De la sortie, nous pouvons voir que chaque thread compte pour lui-même et n'utilise pas la valeur de l'autre:

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow