Buscar..


Observaciones

Se utiliza mejor para objetos que dependen de elementos internos durante la invocación de una llamada, pero de lo contrario no tienen estado, como SimpleDateFormat , Marshaller

Para el uso Random ThreadLocal, considere usar ThreadLocalRandom

ThreadLocal Java 8 inicialización funcional

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

Uso básico de ThreadLocal

Java ThreadLocal se utiliza para crear variables locales de subprocesos. Se sabe que los subprocesos de un Objeto comparten sus variables, por lo que la variable no es segura para subprocesos. Podemos usar la sincronización para la seguridad de los subprocesos, pero si queremos evitar la sincronización, ThreadLocal nos permite crear variables que son locales para el subproceso, es decir, solo ese subproceso puede leer o escribir en esas variables, por lo que los otros subprocesos ejecutan el mismo fragmento de código. no podrá acceder a las variables ThreadLocal de los demás.

Esto puede ser usado, podemos usar variables ThreadLocal . en situaciones en las que tiene un grupo de subprocesos como, por ejemplo, en un servicio web. Por ejemplo, la creación de un objeto SimpleDateFormat cada vez que se realiza cada solicitud requiere mucho tiempo y no se puede crear uno estático, ya que SimpleDateFormat no es seguro para subprocesos, por lo que podemos crear un ThreadLocal para que podamos realizar operaciones seguras para subprocesos sin la sobrecarga de crear SimpleDateFormat cada hora.

La siguiente pieza de código muestra cómo se puede usar:

Cada hilo tiene su propia variable ThreadLocal y pueden usar los métodos get() y set() para obtener el valor predeterminado o cambiar su valor local a Thread.

ThreadLocal instancias de ThreadLocal suelen ser campos estáticos privados en clases que desean asociar el estado con un hilo.

Aquí hay un pequeño ejemplo que muestra el uso de ThreadLocal en el programa java y demuestra que cada hilo tiene su propia copia 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());
    }

}

Salida:

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

Como podemos ver en la salida, Thread-0 ha cambiado el valor de formateador pero aún así el formateador predeterminado de thread-2 es el mismo que el valor inicializado.

Múltiples hilos con un objeto compartido.

En este ejemplo, solo tenemos un objeto, pero se comparte entre / ejecuta en diferentes subprocesos. El uso normal de los campos para guardar el estado no sería posible porque el otro hilo también lo vería (o probablemente no lo vería).

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

En Foo contamos desde cero. En lugar de guardar el estado en un campo, almacenamos nuestro número actual en el objeto ThreadLocal, al que se puede acceder de forma estática. Tenga en cuenta que la sincronización en este ejemplo no está relacionada con el uso de ThreadLocal, sino que garantiza una mejor salida de la consola.

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

Desde la salida podemos ver que cada hilo cuenta por sí mismo y no usa el valor del otro:

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow