Un poco de la conquista ThreadLocal

Lo ThreadLocal
  tan pronto como sea proporcionado en la versión java.lang.ThreadLocal de JDK 1.2, ThreadLocal ofrece una nueva manera de resolver el problema de los programas multihilo simultáneos. El uso de esta herramienta puede ser clase muy simple para escribir una hermosa programas multihilo.
  Cuando se utiliza de mantenimiento variable de ThreadLocal, ThreadLocal proporcionan para cada hilo utilizando la copia variable independiente variable, cada hilo puede cambiar de forma independiente su copia sin afectar a otros hilos de copia correspondientes.
  Desde la perspectiva de la rosca de vista, la variable de destino es como una variable local de rosca, que está destinado a expresar el nombre de clase "local".
  Por lo tanto, el código para escribir las variables de subproceso local en Java que sea relativamente pocos torpe, causando por lo tanto las variables de subproceso local no están bien en la popularidad de los desarrolladores de Java en.
métodos de interfaz ThreadLocal
interfaz de clase ThreadLocal es muy simple, sólo cuatro métodos, vamos a echar un vistazo:
vacío SET (valor del objeto) Establecer el valor de las variables de subproceso local del hilo actual.
get public Object () devuelve el método del hilo de corriente correspondiente a las variables de subproceso local.
público Remove void () el valor de las variables locales del subproceso actual borrada, el propósito es reducir el uso de memoria, que es un nuevo método para JDK 5.0. Cabe señalar que, cuando el extremo del hilo, la variable local hilo debe ser automáticamente la basura, por lo que pide explícitamente este método para limpiar el hilo no se requiere variable local para operar, pero puede acelerar la recuperación de la velocidad de la memoria.
Objeto protegido initialValue () vuelve al valor inicial de las variables locales de hilo, que es un método de una subclases cubierta diseñada protegido, aparentemente para permitir. Este método es un método para llamadas de demora, get llamada () o conjunto (Objeto) cuando la ejecución del hilo por primera vez, y sólo realiza una vez. El valor por defecto en los retornos directos ThreadLocal un nulo.
  Vale la pena mencionar que en JDK5.0, ThreadLocal tiene soporte para los genéricos, la clase del nombre de la clase se ha convertido en ThreadLocal. métodos de la API ha ajustado en consecuencia, la nueva versión de los métodos de la API son conjunto vacío (valor T), T get () y T initialValue ().
  Cómo hacer ThreadLocal es mantener una copia de cada hilo de las variables que? De hecho, la idea es la realización muy simple: Hay un mapa en la clase ThreadLocal, un hilo por cada copia del almacenamiento de variables, elementos clave en el mapa es objeto hilo, y el valor de la variable que corresponde a una copia de la rosca. Nosotros mismos podemos ofrecer una versión simple aplicación:

[java] vista copia simple
com.test paquete;

clase TestNum {public
// ThreadLocal cubierta por las clases internas initialValue ① anónimos () método, que especifica el valor inicial
estático privada ThreadLocal SEQNUM = new nuevo ThreadLocal () {
público el initialValue Entero () {
return 0;
}
};

// ②获取下一个序列值  
public int getNextNum() {  
    seqNum.set(seqNum.get() + 1);  
    return seqNum.get();  
}  

public static void main(String[] args) {  
    TestNum sn = new TestNum();  
    // ③ 3个线程共享sn,各自产生序列号  
    TestClient t1 = new TestClient(sn);  
    TestClient t2 = new TestClient(sn);  
    TestClient t3 = new TestClient(sn);  
    t1.start();  
    t2.start();  
    t3.start();  
}  

private static class TestClient extends Thread {  
    private TestNum sn;  

    public TestClient(TestNum sn) {  
        this.sn = sn;  
    }  

    public void run() {  
        for (int i = 0; i < 3; i++) {  
            // ④每个线程打出3个序列值  
            System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn["  
                     + sn.getNextNum() + "]");  
        }  
    }  
}  

}

Definimos la subclase generalmente a modo clases internas anónimas ThreadLocal proporcionar un valor inicial variables, como en el ejemplo mostrado en ①. Generación de un conjunto de hilos TestClient número de secuencia, el al ③, se generaron tres TestClient, comparten la misma instancia TestNum. Al ejecutar el código anterior, los siguientes resultados de salida en la consola:

del hilo [-0] -> sn [1]
del hilo [-1] -> sn [1]
del hilo [-2] -> sn [1]
del hilo [-1] -> sn [ 2]
del hilo [-0] -> sn [2]
del hilo [-1] -> sn [3]
del hilo [-2] -> sn [2]
del hilo [-0] -> sn [3]
del hilo [-2] -> sn [3]

Inspección salida de información de resultado, se encontró que aunque cada ID del hilo generado comparten el mismo ejemplo TestNum, pero no lo hacen, pueden producirse interferencias, sino que cada número de secuencia generada de forma independiente, esto se debe a que a través de cada ThreadLocal un hilo proporciona copias separadas.

Comparar mecanismo de sincronización de rosca
  mecanismos de sincronización hilo ThreadLocal y cuáles son las ventajas frente a ella? mecanismos ThreadLocal y sincronización hilo se hacen a la dirección de múltiples hilos acceden a la misma conflicto variable.
  En el mecanismo de sincronización por el mecanismo de bloqueo para asegurar que el objeto de la mismo tiempo un solo acceso hilo la variable. Entonces la variable es compartida por múltiples hilos, utilizando un mecanismo de sincronización requiere un cuidadoso análisis de las variables del programa cuando leer y escribir, cuando se necesita para bloquear un objeto, cuándo liberar los complejos problemas de bloqueo de objeto, la programación y la escritura la dificultad es relativamente grande.
  El ThreadLocal desde otro punto de vista para resolver el multi-hilo acceso simultáneo. ThreadLocal proporcionará una copia de las variables independientes para cada hilo, aislando de este modo el conflicto en varios subprocesos acceder a los datos. Debido a que cada hilo tiene su propia copia de la variable, así que no hay necesidad de que la variable de sincronización. ThreadLocal proporcionar un hilo de seguridad objetos compartidos, al escribir código multiproceso se puede encapsular en las variables inseguras ThreadLocal.
  Desde ThreadLocal puede contener cualquier tipo de objeto, la versión baja de JDK proporcionada por get () devuelve un objeto del objeto, necesitamos fundido. JDK 5.0, pero una buena solución a este problema por los genéricos, para simplificar el uso de ThreadLocal, en cierta medida, el código del listado 92 sobre el uso de la nueva versión ThreadLocal JDK 5.0.
  En resumen, para multithreading problemas de distribución de los recursos, los mecanismos de sincronización adoptan la forma de "tiempo para el espacio", que utiliza una forma ThreadLocal "espacio comercial para el tiempo". El primero proporciona una sola variable, por lo que los diferentes hilos de acceder a la cola, cada hilo, mientras que el segundo ofrece una variable, que se puede acceder de forma simultánea y con independencia de los demás es.
  Primavera utiliza ThreadLocal problema de seguridad hilo resolver Sabemos que, en general, sólo se bean sin estado sólo puede ser compartida en un entorno multiproceso, en la primavera, la gran mayoría de la haba se puede declarar como alcance Singleton. Bean es debido a que algunos de Primavera Bean (tales como RequestContextHolder, TransactionSynchronizationManager, LocaleContextHolder, etc.) con el estado thread-safe ThreadLocal África para el procesamiento, de modo que se conviertan en un estado seguro para subprocesos, porque hay estado puede ser compartida en varios subprocesos.
  aplicaciones Web dividen generalmente en la capa de capa de presentación, capa de servicio y la persistencia tres niveles, la preparación de la lógica correspondiente en diferentes capas, la inferior a la superior abierta a través de la función de llamada de interfaz. En general, la recepción de una petición para devolver un procedimiento de respuesta a través del cual todas las llamadas pertenecen a la misma rosca, que se muestra en la Figura 9-2:
Todos apreciaron ThreadLocal dejó en
  el mismo hilo a través de tres por lo que puede necesitar algunas variables no compatibles con el proceso de almacenamiento ThreadLocal, el subproceso de llamada en respuesta a la misma solicitud, todos los objetos asociados están referenciados a la misma variable.
  Los siguientes ejemplos pueden reflejar las ideas de transformación del resorte con estado Bean:
el código del listado 3 TestDao: no thread-safe

[java] vista copia simple
com.test paquete;

java.sql.Connection importación;
java.sql.SQLException importación;
java.sql.Statement importación;

la clase TestDAO {public
conexión privada conn; // ① una variable no seguro para subprocesos

public void addTopic() throws SQLException {  
    Statement stat = conn.createStatement();// ②引用非线程安全变量  
    // …  
}  

}

Desde conn ① en las variables miembro, porque el método addTopic () no es thread-safe, debe crear una nueva instancia de TopicDao (no singleton) cuando está en uso. El siguiente uso de ThreadLocal conn este "estado" no-thread-safe de la transformación:
Listado 4 TestDao: thread-safe

[java] vista copia simple
com.test paquete;

java.sql.Connection importación;
java.sql.SQLException importación;
java.sql.Statement importación;

public class TestDaoNew {
// ①使用ThreadLocal保存conexión变量
estática privada ThreadLocal connThreadLocal = new ThreadLocal ();

public static Connection getConnection() {  
    // ②如果connThreadLocal没有本线程对应的Connection创建一个新的Connection,  
    // 并将其保存到线程本地变量中。  
    if (connThreadLocal.get() == null) {  
        Connection conn = getConnection();  
        connThreadLocal.set(conn);  
        return conn;  
    } else {  
        return connThreadLocal.get();// ③直接返回线程本地变量  
    }  
}  

public void addTopic() throws SQLException {  
    // ④从ThreadLocal中获取线程对应的Connection  
    Statement stat = getConnection().createStatement();  
}  

}

Al utilizar diferentes hilos TopicDao, determinar primero connThreadLocal.get () si es nulo, si es nulo, entonces el hilo actual no tiene la correspondiente objeto de conexión, a continuación, crea un objeto de conexión y el hilo a las variables locales, si no es nulo, entonces el hilo actual ya posee el objeto de conexión para utilizarlo. Por lo tanto, para asegurar que los diferentes hilos de utilizar la conexión de rosca relacionado, conexión sin necesidad de utilizar otros hilos. Por lo tanto, esto se puede hacer TopicDao Singleton compartida.
  Por supuesto, este ejemplo sí es muy áspera, la conexión DAO de ThreadLocal puede hacer directamente en el hilo de los problemas de seguridad no se producen cuando el Compartir conexión múltiples métodos de la DAO, pero no pueden compartir el mismo con otra conexión DAO, para hacer la misma operación Compartir multi-DAO la misma conexión, se debe usar la conexión ThreadLocal guardado en una clase externo común.

ConnectionManager.java

[java] vista copia simple
com.test paquete;

java.sql.Connection importación;
java.sql.DriverManager importación;
java.sql.SQLException importación;

public class {ConnectionManager

private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {  
    @Override  
    protected Connection initialValue() {  
        Connection conn = null;  
        try {  
            conn = DriverManager.getConnection(  
                    "jdbc:mysql://localhost:3306/test", "username",  
                    "password");  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
        return conn;  
    }  
};  

public static Connection getConnection() {  
    return connectionHolder.get();  
}  

public static void setConnection(Connection conn) {  
    connectionHolder.set(conn);  
}  

}

java.lang.ThreadLocal la realización
de que al final es la forma de lograr esta clase ThreadLocal "proveer una variable diferente para cada copia hilo" de la misma? En primer vistazo al código fuente del conjunto ThreadLocal () método es la forma de lograr:

[java] la vista de copia
/ **
* juegos de copias de la hebra actual de esta variable de subproceso local
* en el valor especificado. La mayoría de las subclases no tendrán necesidad de
* reemplazar este método, basándose únicamente en la {@ link #initialValue}
* Método para establecer los valores de rosca-residentes.
*
* @Param valor el valor que se almacena en la copia del flujo actual de
* este local de subprocesos.
* /
Conjunto public void (valor T) {
Thread t = Thread.currentThread ();
ThreadLocalMap mapa = getMap (t);
si (mapa! = null)
map.set (esto, valor);
más
createMap (t, valor);
}

De esta manera vemos dentro, obtener primero un hilo actual y ThreadLocalMap relacionada por el método getMap (Thread t), y luego ajustar el valor de la variable al objeto ThreadLocalMap, por supuesto, si el objeto ThreadLocalMap adquirido está vacía, es por createMap método crea.

el aislamiento de hilo de secretos, mentiras ThreadLocalMap esta clase. clase ThreadLocalMap ThreadLocal es una clase interna estática que pares implementos clave-valor establecer y obtener (Mapa comparación objeto de entender), cada hilo tiene una copia ThreadLocalMap separada de ella valor almacenado, sólo puede ser actual hilo para leer y modificar. ThreadLocal copia de cada clase mediante la operación ThreadLocalMap un hilo específico, consiguiendo de esta manera el acceso variable de aislamiento en diferentes hilos. Debido a que cada variable de rosca son únicos a los suyos, que no tienen errores de concurrencia. Otro punto es que, pares tienda ThreadLocalMap clave-valor en el punto clave es el objeto de esta ThreadLocal objetos, y el valor es el objeto de su puesta en marcha.

Con el fin de profundizar en la comprensión, entonces miramos para lograr getMap y CreateMap métodos que aparecen en el código anterior:

[java] Ver copia simple
/ **

  • Obtener el mapa asociado con un ThreadLocal. se reemplaza en
  • InheritableThreadLocal.
  • @param t el subproceso actual
  • @return el mapa
    * /
    ThreadLocalMap getMap (Tema t) {
    t.threadLocals de retorno;
    }

/ **

  • Crear el mapa asociado con un ThreadLocal. se reemplaza en
  • InheritableThreadLocal.
  • @param t el subproceso actual
  • @param valor firstValue para la entrada inicial del mapa
  • @param trazar el mapa de almacenar.
    * /
    CreateMap vacío (Tema t, T firstValue) {
    t.threadLocals = nueva ThreadLocalMap (esto, firstValue);
    }

A continuación, busque de nuevo método de obtener ThreadLocal clase ():

[java] Ver copia simple
/ **

  • Devuelve el valor en la copia del flujo actual de esta
  • subproceso local variable. Si la variable no tiene valor para el
  • hilo actual, se inicializa primero al valor devuelto
  • por una invocación del método {#initialValue @link}.
  • @return el valor del flujo actual de este subproceso local
    * /
    t consigue pública () {
    Thread t = Thread.currentThread ();
    ThreadLocalMap mapa = getMap (t);
    if (! mapa = null) {
    ThreadLocalMap.Entry e = map.getEntry (this);
    if (! e = null)
    de retorno (T) e.value;
    }
    Devolver setInitialValue ();
    }

Mira setInitialValue () Método:

[java] copia simple vista
/ **
* Variante de set () para establecer initialValue. Usado en lugar
* del set () en caso de que el usuario ha anulado el método set ().
*
* @Return el valor inicial
* /
T setInitialValue () {private
valor T = initialValue ();
Thread t = Thread.currentThread ();
ThreadLocalMap mapa = getMap (t);
si (mapa! = null)
map.set (esto, valor);
más
createMap (t, valor);
valor de retorno;
}

Cuando el valor de la adquisición y el hilo unido a la corriente, objetos ThreadLocalMap ThreadLocal son objeto de este punto es encontrar la clave, por supuesto, el código del método anterior serie () es ecos.

Además, podemos crear diferentes variables de instancia ThreadLocal lograr más aislado en el acceso entre los diferentes hilos, por qué se puede hacer? Debido diferente ThreadLocal objetos como claves diferentes, por supuesto, un valor diferente puede fijarse en el hilo objeto ThreadLocalMap. Por ThreadLocal objetos, una distinción compartida valores y los valores múltiples en múltiples hilos, del mismo modo que almacenar un pares de valores clave en un objeto HashMap y una pluralidad de pares de valores clave, como, nada más.

Resumen
  ThreadLocal problema de seguridad hilo es la manera de resolver una muy buena, que resuelve el problema de los conflictos de acceso concurrente variables, proporcionando un hilo separado para cada copia de la variable. En muchos casos, ThreadLocal que el uso de mecanismos de sincronización hilo sincronizados para solucionar problemas de seguridad más simple, más conveniente, y los resultados del programa tienen una mayor concurrencia.
ConnectionManager.java

[java] vista copia simple
com.test paquete;

java.sql.Connection importación;
java.sql.DriverManager importación;
java.sql.SQLException importación;

public class {ConnectionManager

private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {  
    @Override  
    protected Connection initialValue() {  
        Connection conn = null;  
        try {  
            conn = DriverManager.getConnection(  
                    "jdbc:mysql://localhost:3306/test", "username",  
                    "password");  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
        return conn;  
    }  
};  

public static Connection getConnection() {  
    return connectionHolder.get();  
}  

public static void setConnection(Connection conn) {  
    connectionHolder.set(conn);  
}  

}

Postscript
  ver amigos comentario es muy fuerte, incluso en el interior de ThreadLocalMap no ThreadLocal, pero dentro de este hilo comentarios han surgido, por lo que con este epílogo, pegue el siguiente código fuente del JDK primera, la fuente de la más convincente.

[java] plena vista copia
** /
* ThreadLocalMap es un mapa hash personalizado adecuado sólo para
* mantener los valores locales de rosca. No hay operaciones se exportan
fuera de la clase * ThreadLocal. La clase es un paquete privado a
* permitir la declaración de campos en la clase Thread. Para hacer frente con ayuda
* usos muy grandes y de larga duración, las entradas de la tabla de hash usan
WeakReferences * para las llaves. Sin embargo, ya que las colas de referencia no se
* utilizados, entradas obsoletas están garantizados para ser eliminado sólo cuando
* la tabla comienza la falta de espacio.
* /
Clase estática ThreadLocalMap {...}

El código fuente es más, lo que es una fuente natural en el interior ThreadLocal, hay capturas de pantalla como prueba.

Este artículo es el mismo en el aprendizaje del ThreadLocal, en un capricho, mirado profunda fuente de dicho papel pensamiento, el alcance, y luego pensar en el tradicional sincronizar compartida variables se compararon los problemas de hilo de seguridad y que se resumen Bowen, un resumen a continuación, que es un mecanismo de bloqueo es tiempo de espacio, llevado a un espacio de almacenamiento de copia por el tiempo.

Publicado 33 artículos originales · ganado elogios 0 · Vistas 853

Supongo que te gusta

Origin blog.csdn.net/ninth_spring/article/details/104417537
Recomendado
Clasificación