1 package uk.org.lidalia.lang;
2
3 import static java.lang.Thread.currentThread;
4 import static java.util.Objects.requireNonNull;
5 import static java.util.Optional.ofNullable;
6
7 import java.util.Collection;
8 import java.util.Map;
9 import java.util.concurrent.ConcurrentHashMap;
10 import java.util.function.Supplier;
11
12
13
14
15
16
17
18
19
20
21
22
23 public class ThreadLocal<T> {
24
25 private final Map<Thread, T> contents = new ConcurrentHashMap<>();
26 private final Supplier<T> initialValueCreator;
27 private final Supplier<T> threadValueInitialiser =
28 new Supplier<T>() {
29 @Override
30 public T get() {
31 final T initialValue = initialValueCreator.get();
32 set(initialValue);
33 return initialValue;
34 }
35 };
36
37
38
39
40
41 public ThreadLocal(final T initialValue) {
42 this(() -> requireNonNull(initialValue));
43 }
44
45
46
47
48
49
50 public ThreadLocal(final Supplier<T> initialValueCreator) {
51 this.initialValueCreator = requireNonNull(initialValueCreator);
52 }
53
54
55
56
57
58 public void set(final T value) {
59 contents.put(currentThread(), requireNonNull(value));
60 }
61
62
63
64
65
66 public T get() {
67 return ofNullable(contents.get(currentThread())).orElseGet(threadValueInitialiser);
68 }
69
70
71
72
73
74 public void remove() {
75 contents.remove(currentThread());
76 }
77
78
79
80
81
82 public void reset() {
83 contents.clear();
84 }
85
86 public Collection<T> allValues() {
87 return contents.values();
88 }
89 }