Skip to content

Commit 831a951

Browse files
committed
Polish ConcurrentLruCache
This commit improves the performance of the `ConcurrentLruCache` and applies a consistent style to the code: * separating read/write locks into different variables does not help performance, so this change is reverted * apply a consistent style for read/write locks and try/cactch calls * the reordering of recently used keys is only done when the cache is full Fixes gh-24671
1 parent 713a112 commit 831a951

File tree

1 file changed

+15
-27
lines changed

1 file changed

+15
-27
lines changed

spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,7 +30,6 @@
3030
import java.util.Random;
3131
import java.util.concurrent.ConcurrentHashMap;
3232
import java.util.concurrent.ConcurrentLinkedQueue;
33-
import java.util.concurrent.locks.Lock;
3433
import java.util.concurrent.locks.ReadWriteLock;
3534
import java.util.concurrent.locks.ReentrantReadWriteLock;
3635
import java.util.function.Function;
@@ -421,9 +420,7 @@ private static class ConcurrentLruCache<K, V> {
421420

422421
private final ConcurrentHashMap<K, V> cache = new ConcurrentHashMap<>();
423422

424-
private final Lock readLock;
425-
426-
private final Lock writeLock;
423+
private final ReadWriteLock lock;
427424

428425
private final Function<K, V> generator;
429426

@@ -434,43 +431,36 @@ public ConcurrentLruCache(int maxSize, Function<K, V> generator) {
434431
Assert.notNull(generator, "Generator function should not be null");
435432
this.maxSize = maxSize;
436433
this.generator = generator;
437-
438-
ReadWriteLock lock = new ReentrantReadWriteLock();
439-
this.readLock = lock.readLock();
440-
this.writeLock = lock.writeLock();
434+
this.lock = new ReentrantReadWriteLock();
441435
}
442436

443437
public V get(K key) {
444-
V cached;
445-
446-
if ((cached = this.cache.get(key)) != null) {
447-
if (this.size < this.maxSize / 2) {
438+
V cached = this.cache.get(key);
439+
if (cached != null) {
440+
if (this.size < this.maxSize) {
448441
return cached;
449442
}
450-
443+
this.lock.readLock().lock();
451444
try {
452-
this.readLock.lock();
453-
this.queue.add(key);
454445
this.queue.remove(key);
446+
this.queue.add(key);
455447
return cached;
456448
}
457449
finally {
458-
this.readLock.unlock();
450+
this.lock.readLock().unlock();
459451
}
460452
}
461-
462-
this.writeLock.lock();
453+
this.lock.writeLock().lock();
463454
try {
464-
// retrying in case of concurrent reads on the same key
465-
if ((cached = this.cache.get(key)) != null) {
466-
this.queue.add(key);
455+
// Retrying in case of concurrent reads on the same key
456+
cached = this.cache.get(key);
457+
if (cached != null) {
467458
this.queue.remove(key);
459+
this.queue.add(key);
468460
return cached;
469461
}
470-
471462
// Generate value first, to prevent size inconsistency
472463
V value = this.generator.apply(key);
473-
474464
int cacheSize = this.size;
475465
if (cacheSize == this.maxSize) {
476466
K leastUsed = this.queue.poll();
@@ -479,15 +469,13 @@ public V get(K key) {
479469
cacheSize--;
480470
}
481471
}
482-
483472
this.queue.add(key);
484473
this.cache.put(key, value);
485474
this.size = cacheSize + 1;
486-
487475
return value;
488476
}
489477
finally {
490-
this.writeLock.unlock();
478+
this.lock.writeLock().unlock();
491479
}
492480
}
493481
}

0 commit comments

Comments
 (0)