Utilizando ThreadLocal en las variables de instancia

Do JavaThreadLocal variables producen valores locales de hilo si se usan como variables de instancia (por ejemplo, en un método que genera objetos locales de subprocesos), ¿o deben ser siempre estáticos para hacerlo?

Como ejemplo, suponga un escenario típico en el que varios objetos costosos para inicializar de una clase que no son seguros para subprocesos deben instanciarse en un solo bloque de inicialización estática, almacenados en variables estáticas de una sola clase (por ejemplo, en un @Map estructura de datos) y desde entonces se utiliza para el procesamiento intensivo por numerosos subprocesos diferentes.

Para lograr la seguridad del hilo, obviamente se debe pasar una copia diferente de cada objeto estático. Por ejemplo, JavaDateFormat objetos que deben usarse de manera segura en diferentes subprocesos.

n muchos ejemplos que se pueden encontrar en la web, el enfoque parece declarar por separado cadaThreadLocal variable, instanciar el nuevo objeto en lainitialValue() y luego use elget() método para recuperar una instancia de subproceso local.

Este enfoque no es muy eficiente si hay docenas o cientos de tales objetos para crear, cada uno con sus propios parámetros de inicialización. Por ejemplo, muchosSimpleDateFormat objetos con un patrón de fecha diferente cada uno.

Si la creación de instancias de los objetos se pudiera hacer en un bucle que produce un valor diferente en cada iteración, se necesitaría un método genérico para producir las instancias de subprocesos locales, después de crear cada valor inicializando correctamente el objeto correspondiente.

Basado en lo anterior, el siguiente método estático genérico no funcionaría, porque se genera la misma referencia en cada llamada a initialValue ():

// Each value is an object initialized prior to calling getLocal(...)
public static final <T> T getLocal(final T value)
{
    ThreadLocal<T> local = new ThreadLocal<T>()
    {
        @Override
        protected T initialValue()
        {
            return value;
        }
    };

    return local.get();
}

En cambio, se necesita un mecanismo para crear un nuevo objeto dentro de initialValue (). Entonces, el único enfoque genérico es probablemente usar la reflexión, en un patrón similar a

private static final <T> T getLocal(
        final Constructor<T> constructor, final Object[] initargs)
{
    ThreadLocal<T> local = new ThreadLocal<T>()
    {           
        @Override
        protected T initialValue()
        {
            T value = null;

            try // Null if the value object cannot be created
            {
                value = constructor.newInstance(initargs);
            }
            catch (Exception e)
            {
            }

            return value;
        }
    };

    return local.get();
}

ntonces, por supuesto, existe la opción específica del tipo, donde uno podría usar laThreadLocal patrón en el bucle para declarar cada variable.

Por ejemplo, en el caso deDateFormat, en un solo bloque de inicialización estática, uno podría hacer

private static String[] patterns = ... // Get date patterns
private static DateFormat format;

public static Map<String, DateFormat> formats = new HashMap<String, DateFormat>();

static
{
    for (final String pattern:patterns)
    {
        format = new ThreadLocal<DateFormat>()
        {           
                @Override
            protected DateFormat initialValue()
                {
            return new SimpleDateFormat(pattern);
            }
        }.get();

        formats.put(pattern, format);
}

Desde entonces, laformats map será leído por diferentes clases, a través de diferentes hilos, cada vez para invocar elformat() oparse() método de uno o másDateFormat objetos almacenados en el mapa.

Alguno de los enfoques anteriores tiene sentido para el caso descrito, o debería elThreadLocal declaraciones ser estáticas?

Respuestas a la pregunta(4)

Su respuesta a la pregunta