3535import java .util .Map ;
3636import java .util .Optional ;
3737import java .util .concurrent .CompletableFuture ;
38+ import java .util .concurrent .locks .Lock ;
39+ import java .util .concurrent .locks .ReentrantLock ;
3840import java .util .function .BiConsumer ;
3941import java .util .function .Consumer ;
4042
@@ -77,6 +79,7 @@ public class DataLoader<K, V extends @Nullable Object> {
7779 private final ValueCache <K , V > valueCache ;
7880 private final DataLoaderOptions options ;
7981 private final Object batchLoadFunction ;
82+ final Lock lock ;
8083
8184 @ VisibleForTesting
8285 DataLoader (@ Nullable String name , Object batchLoadFunction , @ Nullable DataLoaderOptions options ) {
@@ -93,7 +96,7 @@ public class DataLoader<K, V extends @Nullable Object> {
9396 this .batchLoadFunction = nonNull (batchLoadFunction );
9497 this .options = loaderOptions ;
9598 this .name = name ;
96-
99+ this . lock = new ReentrantLock ();
97100 this .helper = new DataLoaderHelper <>(this , batchLoadFunction , loaderOptions , this .futureCache , this .valueCache , this .stats , clock );
98101 }
99102
@@ -265,18 +268,16 @@ public CompletableFuture<List<V>> loadMany(List<K> keys, List<Object> keyContext
265268 nonNull (keys );
266269 nonNull (keyContexts );
267270
268- synchronized (this ) {
269- List <CompletableFuture <V >> collect = new ArrayList <>(keys .size ());
270- for (int i = 0 ; i < keys .size (); i ++) {
271- K key = keys .get (i );
272- Object keyContext = null ;
273- if (i < keyContexts .size ()) {
274- keyContext = keyContexts .get (i );
275- }
276- collect .add (loadImpl (key , keyContext ));
271+ List <CompletableFuture <V >> collect = new ArrayList <>(keys .size ());
272+ for (int i = 0 ; i < keys .size (); i ++) {
273+ K key = keys .get (i );
274+ Object keyContext = null ;
275+ if (i < keyContexts .size ()) {
276+ keyContext = keyContexts .get (i );
277277 }
278- return CompletableFutureKit . allOf ( collect );
278+ collect . add ( loadImpl ( key , keyContext ) );
279279 }
280+ return CompletableFutureKit .allOf (collect );
280281 }
281282
282283 /**
@@ -296,15 +297,13 @@ public CompletableFuture<List<V>> loadMany(List<K> keys, List<Object> keyContext
296297 public CompletableFuture <Map <K , V >> loadMany (Map <K , ?> keysAndContexts ) {
297298 nonNull (keysAndContexts );
298299
299- synchronized (this ) {
300- Map <K , CompletableFuture <V >> collect = new HashMap <>(keysAndContexts .size ());
301- for (Map .Entry <K , ?> entry : keysAndContexts .entrySet ()) {
302- K key = entry .getKey ();
303- Object keyContext = entry .getValue ();
304- collect .put (key , loadImpl (key , keyContext ));
305- }
306- return CompletableFutureKit .allOf (collect );
300+ Map <K , CompletableFuture <V >> collect = new HashMap <>(keysAndContexts .size ());
301+ for (Map .Entry <K , ?> entry : keysAndContexts .entrySet ()) {
302+ K key = entry .getKey ();
303+ Object keyContext = entry .getValue ();
304+ collect .put (key , loadImpl (key , keyContext ));
307305 }
306+ return CompletableFutureKit .allOf (collect );
308307 }
309308
310309 /**
@@ -380,9 +379,12 @@ public DataLoader<K, V> clear(K key) {
380379 */
381380 public DataLoader <K , V > clear (K key , BiConsumer <Void , Throwable > handler ) {
382381 Object cacheKey = getCacheKey (key );
383- synchronized (this ) {
382+ try {
383+ lock .lock ();
384384 futureCache .delete (cacheKey );
385385 valueCache .delete (key ).whenComplete (handler );
386+ } finally {
387+ lock .unlock ();
386388 }
387389 return this ;
388390 }
@@ -404,9 +406,12 @@ public DataLoader<K, V> clearAll() {
404406 * @return the data loader for fluent coding
405407 */
406408 public DataLoader <K , V > clearAll (BiConsumer <Void , Throwable > handler ) {
407- synchronized (this ) {
409+ try {
410+ lock .lock ();
408411 futureCache .clear ();
409412 valueCache .clear ().whenComplete (handler );
413+ } finally {
414+ lock .unlock ();
410415 }
411416 return this ;
412417 }
@@ -446,10 +451,13 @@ public DataLoader<K, V> prime(K key, Exception error) {
446451 */
447452 public DataLoader <K , V > prime (K key , CompletableFuture <V > value ) {
448453 Object cacheKey = getCacheKey (key );
449- synchronized (this ) {
454+ try {
455+ lock .lock ();
450456 if (!futureCache .containsKey (cacheKey )) {
451457 futureCache .set (cacheKey , value );
452458 }
459+ } finally {
460+ lock .unlock ();
453461 }
454462 return this ;
455463 }
0 commit comments