From 9ee12f3e45a157ca2fe69764496ca25bfb93decf Mon Sep 17 00:00:00 2001 From: catbref Date: Fri, 12 Jul 2019 13:27:01 +0100 Subject: [PATCH] Reduce execute-produce-consume excessive thread spawning. Defer the clearing of hasThreadPending flag until about to produce a task, inside synchronized block. This gives a new thread a chance to produce at least once before other threads decide to spawn new threads. Previously there could be an excessive number of unncessary threads, all waiting for their initial attempt to produce a task. --- .../java/org/qora/utils/ExecuteProduceConsume.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/qora/utils/ExecuteProduceConsume.java b/src/main/java/org/qora/utils/ExecuteProduceConsume.java index 44d2d6fc..ccba247a 100644 --- a/src/main/java/org/qora/utils/ExecuteProduceConsume.java +++ b/src/main/java/org/qora/utils/ExecuteProduceConsume.java @@ -74,6 +74,7 @@ public abstract class ExecuteProduceConsume implements Runnable { public void run() { Thread.currentThread().setName(className + "-" + Thread.currentThread().getId()); + boolean wasThreadPending; synchronized (this) { ++activeThreadCount; if (activeThreadCount > greatestActiveThreadCount) @@ -82,7 +83,8 @@ public abstract class ExecuteProduceConsume implements Runnable { logger.trace(() -> String.format("[%d] started, hasThreadPending was: %b, activeThreadCount now: %d", Thread.currentThread().getId(), hasThreadPending, activeThreadCount)); - hasThreadPending = false; + // Defer clearing hasThreadPending to prevent unnecessary threads waiting to produce... + wasThreadPending = hasThreadPending; } try { @@ -94,6 +96,12 @@ public abstract class ExecuteProduceConsume implements Runnable { logger.trace(() -> String.format("[%d] waiting to produce...", Thread.currentThread().getId())); synchronized (this) { + if (wasThreadPending) { + // Clear thread-pending flag now that we about to produce. + hasThreadPending = false; + wasThreadPending = false; + } + final boolean lambdaCanIdle = canBlock; logger.trace(() -> String.format("[%d] producing, canBlock is %b...", Thread.currentThread().getId(), lambdaCanIdle)); task = produceTask(canBlock);