Reputation: 179
The class Collector was created to generate the map with values (for example). Need that Collector contains the resource, where haves access only by the current thread.
The class Collector is presented below:
public class Collector
{
ThreadLocal<Map<String, String>> storage;
public Map<String, String> collection(int id) {
storage = new ThreadLocal<>();
storage.set(new HashMap<>());
for (int i = id * 100; i <= id * 1000; i+=id * 100)
{
storage.get().put(String.valueOf(i), "test");
}
return storage.get();
}
}
I try to execute method collection(int id)
at the same time in different threads. My suggestion is based the official documentation. But sometimes thrown NullPointerException, my observations point out on re-creating ThreadLocal by another Thread, so NullPointerException throw in the storage.get().put(String.valueOf(i), "test");
, because in the another thread in the line storage = new ThreadLocal<>();
was re-initialized.
Below presented code, where run two threads:
Collector collector = new Collector();
new Thread(new Runnable()
{
@Override
public void run()
{
System.out.println(collector.collection(1));
}
}).start();
new Thread(new Runnable()
{
@Override
public void run()
{
System.out.println(collector.collection(2));
}
}).start();
How I can use the ThreadLocal to have local resource in each thread, which is independence from another threads?
Upvotes: 1
Views: 140
Reputation: 21152
The problem is that you're re-creating a new ThreadLocal
instance each time the
collection(int)
method is called, with
this.storage = new ThreadLocal<>();
The ThreadLocal<Map<String, String>>
can be a class static
field
private final static ThreadLocal<Map<String, String>> STORAGE = new ThreadLocal<>();
To set and get the Thread
's associated value, just use
// You're better off passing and using an already constructed instance
STORAGE.set(new HashMap<>());
STORAGE.get();
Upvotes: 2