@@ -116,7 +116,7 @@ Improving scalability
116
116
- [ Critical section is as small as possible?] ( #minimize-critical-sections )
117
117
- [ Can use ` ConcurrentHashMap.compute() ` or Guava's ` Striped ` for per-key locking?
118
118
] ( #increase-locking-granularity )
119
- - [ Can replace blocking collection or a queue with a concurrent one?] ( #non-blocking-collections )
119
+ - [ Can replace a blocking collection or a queue with a concurrent one?] ( #non-blocking-collections )
120
120
- [ Can use ` ClassValue ` instead of ` ConcurrentHashMap<Class, ...> ` ?] ( #use-class-value )
121
121
- [ Considered ` ReadWriteLock ` (or ` StampedLock ` ) instead of a simple lock?] ( #read-write-lock )
122
122
- [ ` StampedLock ` is used instead of ` ReadWriteLock ` when reentrancy is not needed?
@@ -126,6 +126,7 @@ Improving scalability
126
126
- [ Considered queues from JCTools instead of the standard concurrent queues?] ( #jctools )
127
127
- [ Considered Caffeine cache instead of other caching libraries?] ( #caffeine )
128
128
- [ Can apply speculation (optimistic concurrency) technique?] ( #speculation )
129
+ - [ Considered ` ForkJoinPool ` instead of ` newFixedThreadPool(N) ` ?] ( #fjp-instead-tpe )
129
130
130
131
Lazy initialization and double-checked locking
131
132
- [ Lazy initialization of a field should be thread-safe?] ( #lazy-init-thread-safety )
@@ -1001,9 +1002,13 @@ blocking ones?** Here are some possible replacements within JDK:
1001
1002
- ` LinkedBlockingQueue ` → ` ConcurrentLinkedQueue `
1002
1003
- ` LinkedBlockingDeque ` → ` ConcurrentLinkedDeque `
1003
1004
1004
- Also consider using queues from JCTools instead of concurrent queues from the JDK: see
1005
+ Consider also using queues from JCTools instead of concurrent queues from the JDK: see
1005
1006
[ Sc.8] ( #jctools ) .
1006
1007
1008
+ See also an item about using [ ` ForkJoinPool ` instead of ` newFixedThreadPool(N) ` ] ( #fjp-instead-tpe )
1009
+ for high-traffic executor services, which internally amounts to replacing a single blocking queue of
1010
+ tasks inside ` ThreadPoolExecutor ` with multiple non-blocking queues inside ` ForkJoinPool ` .
1011
+
1007
1012
<a name =" use-class-value " ></a >
1008
1013
[ #] ( #use-class-value ) Sc.4. Is it possible to ** use [ ` ClassValue ` ] (
1009
1014
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ClassValue.html ) instead of
@@ -1077,6 +1082,21 @@ This principle is used internally in many scalable concurrent data structures, i
1077
1082
See also the article about [ Optimistic concurrency control] (
1078
1083
https://en.wikipedia.org/wiki/Optimistic_concurrency_control ) on Wikipedia.
1079
1084
1085
+ <a name =" fjp-instead-tpe " ></a >
1086
+ [ #] ( #fjp-instead-tpe ) Sc.11. Was it considered to ** use a ` ForkJoinPool ` instead of a
1087
+ ` ThreadPoolExecutor ` with N threads** (e. g. returned from one of ` Executors.newFixedThreadPool() `
1088
+ methods), for thread pools on which a lot of small tasks are executed? ` ForkJoinPool ` is more
1089
+ scalable because internally it maintains one queue per each worker thread, whereas
1090
+ ` ThreadPoolExecutor ` has a single, blocking task queue shared among all threads.
1091
+
1092
+ ` ForkJoinPool ` implements ` ExecutorService ` as well as ` ThreadPoolExecutor ` , so could often be a
1093
+ drop in replacement. For caveats and details, see [ this] (
1094
+ http://cs.oswego.edu/pipermail/concurrency-interest/2020-January/017058.html ) and [ this] (
1095
+ http://cs.oswego.edu/pipermail/concurrency-interest/2020-February/017061.html ) messages by Doug Lea.
1096
+
1097
+ See also items about [ using non-blocking collections (including queues) instead of blocking
1098
+ ones] ( #non-blocking-collections ) and about [ using JCTools queues] ( #jctools ) .
1099
+
1080
1100
<a name =" lazy-init " ></a >
1081
1101
### Lazy initialization and double-checked locking
1082
1102
0 commit comments