Do Java variables provide ThreadLocallocal stream values ββif they are used as instance variables (for example, in a method that generates stream-local objects), or should they always be static like that?
As an example, suppose that a typical scenario is when several, expensive for initializing class objects that are not thread safe, need to be created in one static initialization block, stored in static variables of the same class (for example, in a data structure Map), and then used for intensive processing many different threads.
To ensure thread safety, obviously, another copy of each static object must be passed. For example, Java objects DateFormatthat must be safely used for different threads.
In many examples that can be found on the Internet, the approach seems to declare each variable separately ThreadLocal, instantiate a new object in the method initialValue(), and then use the method get()to get the stream-local instance.
This approach is not very effective if you need to create tens or hundreds of such objects, each of which has its own initialization parameters. For example, many objects SimpleDateFormatwith a different date pattern each.
If instantiation of objects can be performed in a loop that produces a different value in each iteration, a general method is needed to create local thread instances after each value is created by properly initializing the corresponding object.
Based on the foregoing, the following general static method will not work, because the same link is created every time initialValue () is called:
public static final <T> T getLocal(final T value)
{
ThreadLocal<T> local = new ThreadLocal<T>()
{
@Override
protected T initialValue()
{
return value;
}
};
return local.get();
}
Instead, a mechanism is needed to create a new object inside initialValue (). Thus, the only general approach probably uses reflection in a template similar to
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
{
value = constructor.newInstance(initargs);
}
catch (Exception e)
{
}
return value;
}
};
return local.get();
}
Then, of course, there is a type specification in which you can simply use a template ThreadLocalin a loop to declare each variable.
, DateFormat
private static String[] 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);
}
formats , format() parse() DateFormat, .
- ThreadLocal?