Introducción a ThreadLocal en Java

ThreadLocal en Java

ThreadLocal en Java


En este artículo vamos a realizar una introducción a ThreadLocal en Java, el cual se encuentra dentro de java.lang.

El uso de ThreadLocal nos va a permitir guardar y/o almacenar información para el Thread actual en el que se encuentra esa petición, por ejemplo podríamos guardar información de autenticación o autorización de un usuario.

¿Cuándo hacer uso del ThreadLocal en Java?

El uso de ThreadLocal nos va a ser de gran ayudar para guardar información durante dura una petición. Por ejemplo, como hemos comentado en la introducción para guardar información del token del usuario que ha realizado la petición o guardar información de un pedido en una tienda virtual.

Imagina que vamos a realizar una transferencia de dinero dentro de nuestro banco, y necesitamos guardar el id de la transacción que acabamos de realizar. Propagar el id de la transacción por cada método puede acarrear repetir código, pero en cambio si lo guardamos en el ThreadLocal sabemos que mientras dure esa petición (request), podrá ser recuperado en cualquier momento.

Clase ThreadLocal

Vamos a echar un vistazo a la clase ThreadLocal :

public class ThreadLocal<T>

La clase ThreadLocal nos proporciona variables thread-local. Estas variables son independientes y cada acceso es propio, manteniendo su independencia.

Por lo general, las instancias de ThreadLocal son private static, de manera que podemos asociar el estado de lo que queremos guardar al thread.

Los principales métodos que tiene la clase ThreadLocal son:

  • get(): Devuelve el valor del actual Thread.
  • initValue(): Devuelve el valor inicial del actual Thread para la variable thread-local.
  • remove(): Elimina el valor del actual thread para la variable thread-local.
  • set(T value): Establece un valor para el actual thread.

Uso del API de ThreadLocal

Vamos a ver como podemos hacer uso para guardar y recuperar información que guardemos en el ThreadLocal, la cual únicamente puede ser recuperar por el Thread actual.

La clase ThreadLocal acepta tipos genéricos, por lo que por ejemplo podemos crear un ThreadLocal de tipo String:

ThreadLocal<String> threadLocalValue = new ThreadLocal<>();

Una vez hemos creado nuestro ThreadLocal vamos a utilizar este nuevo ThreadLocal, para ello primero vamos a guardar un valor en nuestro Thread haciendo uso del método set().

threadLocalValue.set("say Hi");

Una vez hemos guardado un valor en la variable ThreadLocal vamos a recuperarlo con get().

String value = threadLocalValue.get();

Si queremos eliminar el valor de nuestro ThreadLocal podemos hacer uso de remove().

threadLocalValue.remove();

También podemos hacer uso de withInitial() para a través de un supplier guardar información en nuestro ThreadLocal.

ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> "say Hi");

Uso de Thread Pool con ThreadLocal

El uso de ThreadLocal, a parte de ser útil para guardar información de esa petición, es thread safe por lo que esa información de ese Thread se mantendrá. Pero qué ocurre cuando trabajamos con un Thread Pool y no limpiamos bien ese Thread?.

Cuando hacemos uso de Thread Pool, el Thread volverá al Pool de Threads una vez finaliza su trabajo. A continuación ese Thread devuelto puede ser requerido otra vez para realizar otro proceso, el problema surge cuando re-utilizamos ese Thread sin haber sido limpiado, ya que podrá tener información que hemos guardado del proceso anterior.

Para evitar los problemas de reutilización de Threads con posible información de otras ejecuciones tendremos que limpiar el Thread antes o después de su ejecución mediante el uso de la clase ThreadPoolExecutor, vamos a verlo con código:

public class ThreadLocalWithThreadPool extends ThreadPoolExecutor {

  public ThreadLocalWithThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime,
      TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
  }

  @Override
  protected void afterExecute(Runnable r, Throwable t) {
  }

  @Override
  protected void beforeExecute(Thread t, Runnable r)  {
    
  }

}

Conclusión

En esta entrada sobre introducción a ThreadLocal en Java hemos entendido un poco mejor el funcionamiento y uso de ThreadLocal como una utilidad de Java que nos va a permitir almacenar y utilizar determinada información en el Thread actual.

Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *