From 33f0b8ec4aa9a21006c6005d59d2504344f2e35e Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 8 Jun 2023 11:23:09 -0400 Subject: [PATCH] Optimize synchronized in PartitionedDispatcher (#8640) Even if the `PartitionedDispatcher.populatedPartitions()` is fast, in-memory, non-blocking operation, its active call from the `dispatch()` on every message sent to the channel may pin the virtual thread. * Optimize the `populatedPartitions()` for double `if` where we will step into a `synchronized` block only for first several concurrent messages **Cherry-pick to `6.1.x`** --- .../dispatcher/PartitionedDispatcher.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/dispatcher/PartitionedDispatcher.java b/spring-integration-core/src/main/java/org/springframework/integration/dispatcher/PartitionedDispatcher.java index 2b727ac61a..1883f190fa 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/dispatcher/PartitionedDispatcher.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/dispatcher/PartitionedDispatcher.java @@ -151,10 +151,16 @@ public class PartitionedDispatcher extends AbstractDispatcher { return partitionDispatcher.dispatch(message); } - private synchronized void populatedPartitions() { + private void populatedPartitions() { if (this.partitions.isEmpty()) { - for (int i = 0; i < this.partitionCount; i++) { - this.partitions.put(i, newPartition()); + synchronized (this.partitions) { + if (this.partitions.isEmpty()) { + Map partitionsToUse = new HashMap<>(); + for (int i = 0; i < this.partitionCount; i++) { + partitionsToUse.put(i, newPartition()); + } + this.partitions.putAll(partitionsToUse); + } } } }