Skip to content

Commit a8aa074

Browse files
committed
DATACMNS-1735 - Polishing.
Use mutated object as guard for synchronization. Copy discovered callbacks to cached callbacks. Reduce concurrency in unit test to reduce test load. Guard synchronization with timeouts. Original pull request: #446.
1 parent 0e95440 commit a8aa074

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -384,10 +384,11 @@ Collection<EntityCallback<?>> getEntityCallbacks() {
384384
if (this.entityCallbackBeans.isEmpty()) {
385385

386386
if (cachedEntityCallbacks.size() != entityCallbacks.size()) {
387-
List<EntityCallback<?>> entityCallbacks = new ArrayList<>(this.entityCallbacks.size());
387+
388+
List<EntityCallback<?>> entityCallbacks = new ArrayList<>(this.entityCallbacks);
388389
AnnotationAwareOrderComparator.sort(entityCallbacks);
389390

390-
synchronized(this) {
391+
synchronized (cachedEntityCallbacks) {
391392
cachedEntityCallbacks.clear();
392393
cachedEntityCallbacks.addAll(entityCallbacks);
393394
}

src/test/java/org/springframework/data/mapping/callback/EntityCallbackDiscovererUnitTests.java

+17-10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import java.util.List;
2222
import java.util.concurrent.CopyOnWriteArrayList;
2323
import java.util.concurrent.CountDownLatch;
24+
import java.util.concurrent.LinkedBlockingDeque;
25+
import java.util.concurrent.ThreadPoolExecutor;
26+
import java.util.concurrent.TimeUnit;
2427

2528
import org.junit.jupiter.api.Test;
2629
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -35,8 +38,11 @@
3538
import org.springframework.data.mapping.PersonDocument;
3639

3740
/**
41+
* Unit tests for {@link EntityCallbackDiscoverer}.
42+
*
3843
* @author Christoph Strobl
3944
* @author Myeonghyeon Lee
45+
* @author Mark Paluch
4046
*/
4147
class EntityCallbackDiscovererUnitTests {
4248

@@ -59,30 +65,31 @@ void shouldDiscoverCallbackTypeConcurrencyCache() throws InterruptedException {
5965
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
6066

6167
EntityCallbackDiscoverer discoverer = new EntityCallbackDiscoverer(ctx);
62-
63-
int concurrencyCount = 4000;
64-
CountDownLatch startLatch = new CountDownLatch(concurrencyCount);
65-
CountDownLatch doneLatch = new CountDownLatch(concurrencyCount);
68+
int poolSize = Runtime.getRuntime().availableProcessors();
69+
ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, poolSize, 20, TimeUnit.SECONDS,
70+
new LinkedBlockingDeque<>());
71+
CountDownLatch startLatch = new CountDownLatch(poolSize);
72+
CountDownLatch doneLatch = new CountDownLatch(poolSize);
6673

6774
List<Exception> exceptions = new CopyOnWriteArrayList<>();
68-
for (int i = 0; i < concurrencyCount; i++) {
69-
Thread thread = new Thread(() -> {
75+
for (int i = 0; i < poolSize; i++) {
76+
executor.submit(() -> {
7077
try {
7178
startLatch.countDown();
72-
startLatch.await();
79+
startLatch.await(5, TimeUnit.SECONDS);
7380

7481
discoverer.getEntityCallbacks(PersonDocument.class,
75-
ResolvableType.forType(BeforeSaveCallback.class));
82+
ResolvableType.forType(BeforeSaveCallback.class));
7683
} catch (Exception ex) {
7784
exceptions.add(ex);
7885
} finally {
7986
doneLatch.countDown();
8087
}
8188
});
82-
thread.start();
8389
}
8490

85-
doneLatch.await();
91+
doneLatch.await(10, TimeUnit.SECONDS);
92+
executor.shutdownNow();
8693

8794
assertThat(exceptions).isEmpty();
8895
}

0 commit comments

Comments
 (0)