ThreadLocal: Almacenamiento de variables asociadas con Threads

Entre las clases de Java existe una que se llama ThreadLocal, en el paquete base  . Esta clase puede ser muy útil para optimizar recursos en ambientes concurrentes, ya que su función es guardar una variable asociada con un Thread.

De este modo, podemos tener un componente en nuestra aplicación que si necesita manejar algún tipo de estado por cada Thread que ejecuta alguno de sus métodos, se pueden usar variables ThreadLocal, y en casa hilo que se ejecuta, éstas variables tendrán un valor distinto.

La clase es genérica, lo cual nos permite indicar el tipo de variable que queremos guardar, sin necesidad de estar haciendo casts posteriormente.

La mejor manera de entender el funcionamiento de ThreadLocal es con un ejemplo. Supongamos que tenemos un componente con dos métodos, uno de los cuales crea un objeto y el otro utiliza dicho objeto en algún momento más adelante, una solución es devolver el objeto creado en el primer método, dejando al código que lo invocó la tarea de guardarlo para pasarlo como parámetro al siguiente método. De modo que nuestro componente simplemente es así:

 

Pero qué pasa si estos dos métodos de nuestro componente son también invocados por otro componente que puede estar en un ambiente multi-hilos? Ese otro componente puede guardar el objeto de Estado en un ThreadLocal:

 

En el método   del segundo componente, obtenemos el Estado que debe haber sido generado cuando fue invocado   en el mismo hilo; si no tenemos el objeto es porque   no ha sido invocado aún por el hilo que está invocando  , por lo que debemos presentar algún tipo de error.

Supongamos entonces que tenemos una sola instancia de OtroComponente y una sola instancia de ComponenteSinEstado, ambas están conectadas, y ahora tenemos este código que vamos a correr en dos Threads:

 

Lo que va a ocurrir en este caso es que el primer Thread (llamado "Buena") va a invocar  , lo cual va a terminar guardando una instancia de Estado asociada con el Thread "Buena", que después será obtenida nuevamente en la invocación a   en el mismo hilo, mientras que el segundo Thread (llamado "Mala") va a invocar directamente  , que va a arrojar algún error porque ese hilo ("Mala") no tiene una instancia de Estado asociada a él, ya que el método   no fue invocado ahí; así podemos ver que aunque estamos usando la misma instancia de ComponenteSinEstado y de OtroComponente, al llamarlos desde distintos hilos, la llamada a   devuelve un objeto distinto en cada Thread.

La instancia de Estado que se crea para el Thread "Buena", será válida mientras ese Thread siga vivo; en cuanto termine su ejecución, ese Estado podrá ser eliminado por el recolector de basura, a menos por supuesto que haya otros objetos que tengan una referencia a él.

La clase ThreadLocal tiene un método protegido llamado  , el cual puede ser sobreescrito en subclases para que siempre se devuelva un valor en la primera llamada a  . Esto es útil en otros casos donde se quiere construir un objeto simple que se tenga asociado con cada hilo que lo necesite, y una manera sencilla de hacer uso de dicho método es con una clase anónima, por ejemplo:

 

Espero que con esto quede clara la diferencia entre variables normales y variables tipo ThreadLocal.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Capacitacion

Hola Ezamudio
es posible me brindes un correo de mensajeria instantanea en donde podamos platicar acerca de capacitacion en java, espero tu pronta respuesta,
Saludos

Imagen de ezamudio

no

Lo siento, no doy capacitación por mensajería (ni por ningún otro medio, de hecho). Si tienes dudas y las pones en el sitio con mucho gusto las resuelvo cuando son de algo que conozco.

Imagen de IRr3v3rsible

Aplicaciones de Los hilos (threads)

Hola ezamudio disculpa la molestia, soy estudiante de ISC tercer semestre, solo que me han dejado una tarea donde ponga las aplicaciones de los hilos, no se si me podrias ayudar?...Muchas grax!

Imagen de ezamudio

muchísimas

Simplemente en aplicaciones Swing cualquier tarea que vaya a tomar más de un par de segundos la debes realizar en un hilo separado para no bloquear la interfaz de usuario.

En conexiones de red que usan protocolos asíncronos necesitas un hilo que escribe al socket y otro separado que va leyendo del socket.

Si haces una aplicación que recibe conexiones, necesitas tener un hilo para estar recibiendo esas conexiones en tu ServerSocket y cada que recibes una crear un hilo separado para procesar esa conexión (esto aplica por ejemplo en un web server).

En videojuegos se usan generalmente varios hilos porque tienes uno (o varios) para recibir los eventos del teclado/mouse/joystick/etc, y otros para controlar los demás elementos del juego.

Siempre que pones un Timer o ScheduledExecutorService para programar una tarea que se ejecute más tarde, se va a usar un hilo para ejecutar dicha tarea cuando se tenga que realizar.

Cualquier aplicación web hecha en Java maneja muchísimos hilos, aunque el programador no tenga que lidiar con ellos pero tienes que tener presente que tu código de un servlet o JSP estará siendo ejecutado por varios hilos al mismo tiempo, porque para que la aplicación pueda atender a varios usuarios al mismo tiempo, necesita tener varios hilos corriendo (tal vez no llegue a uno por usuario sino que tenga un ThreadPool pero aun asi vas a tener a varios hilos procesando las peticiones de varios usuarios).

Una consulta ezamudio Los EJB

Una consulta ezamudio
Los EJB stateless se comportan como un bean singleton ?
Los EJB stateful se comportan como un ban singleton ?
Al usar Spring el Controller esta garantizado para funcionar en un ambiente multithread ...? Si el controller yo lo defino como un singleton, Spring lo instancia una sola vez .. pero si hay varios hilos a la vez como asegura Spring que las variables de instancia de un hilo no sean alteradas por otro hilo que se este ejecutando simultaneamente....? Tiene que ver algo el uso de esta clase ThreadLocal?

Imagen de ezamudio

?

Muchas preguntas y no entendi todas, pero esa última: Spring no garantiza nada. Si tienes un componente que Spring maneja como singleton y dicho componente guarda estado, entonces vas a tener problemas si lo usas de manera concurrente.

Tal vez no expliqué bien en el post, pero los ThreadLocals deberían usarse simplemente para almacenar objetos que normalmente son desechables pero cuya creación es "cara" (en términos de RAM o CPU); por ejemplo si tienes código que necesita un SimpleDateFormat o un MessageDigest, puedes crearlo y luego desecharlo, pero si luego encuentras que eso representa un problema en tu aplicación (se usa mucha memoria o el desempeño es lento porque ese código se ejecuta miles de veces por segundo, por diferentes hilos) entonces puedes usar uno o varios ThreadLocal para almacenar ahí esos objetos.