There are different performance trade-offs when reusing objects by storing them as thread-
Thread-local variables are much easier and less expensive to manage than objects in a
pool. Both techniques require you to obtain the initial object: you check it out of the pool,
or you call the get() method on the thread-local object. But object pools require that you
return the object when you are done with it (else no one else can use it); thread-local ob-
jects are always available within the thread and needn't be explicitly returned.
Thread-local variables usually end up with a one-to-one correspondence between the
number of threads and the number of saved (reused) objects. That isn't strictly the case.
The thread's copy of the variable isn't created until the first time the thread uses it, so it is
possible that there are fewer saved objects than threads. But there cannot be any more
saved objects than threads, and much of the time it ends up being the same number.
On the other hand, an object pool may be sized arbitrarily. If a servlet sometimes needs
one JDBC connection and sometimes needs two, the JDBC pool can be sized accordingly
(with, say, 12 connections for 8 threads). Thread-local variables cannot do this effect-
ively; nor can they throttle access to a resource (unless the number of threads itself serves
as the throttle).
Thread-local variables need no synchronization since they can only be used within a
single thread; the thread-local get() method is relatively fast. (This wasn't always the
case; in early versions of Java, obtaining a thread-local variable was quite expensive. If
you shied away from thread-local variables because of bad performance in the past, re-
consider their use in current versions of Java.)
Synchronization brings up an interesting point, because the performance benefit of thread-
local objects is often couched in terms of saving synchronization costs (rather than in the
savings from reusing an object). For example, Java 7 introduced a ThreadLocalRandom
class; that class (rather than a single Random instance) is used in the sample stock applica-
tions. Otherwise, many of the examples throughout the topic would encounter a synchroniza-
tion bottleneck on the next() method of the single Random object. Using a thread-local ob-