From 64e01beeeb9510e3b3bd028ecd0b45dd173a3b06 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 22 Feb 2021 23:02:12 +0100 Subject: [PATCH] Fixes #5994 - QueuedThreadPool "free" threads Introduced to QueuedThreadPool: * getMaxReservedThreads() * getAvailableReservedThreads() * getAvailableThreads() * getReadyThreads() * getLeasedThreads() Also few small code cleanups. Signed-off-by: Simone Bordet --- .../jetty/util/thread/QueuedThreadPool.java | 57 +++++++++++++++---- .../jetty/util/thread/ThreadPoolBudget.java | 17 ++++-- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java index 2408ee877dab..6ae2e1e4de1e 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java @@ -20,8 +20,6 @@ import java.io.Closeable; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -51,7 +49,7 @@ public class QueuedThreadPool extends ContainerLifeCycle implements ThreadFactory, SizedThreadPool, Dumpable, TryExecutor { private static final Logger LOG = Log.getLogger(QueuedThreadPool.class); - private static Runnable NOOP = () -> + private static final Runnable NOOP = () -> { }; @@ -158,6 +156,7 @@ public void setThreadPoolBudget(ThreadPoolBudget budget) { if (budget != null && budget.getSizedThreadPool() != this) throw new IllegalArgumentException(); + updateBean(_budget, budget); _budget = budget; } @@ -425,16 +424,34 @@ public int getMinThreads() * @return number of reserved threads or or -1 for heuristically determined * @see #setReservedThreads */ - @ManagedAttribute("the number of reserved threads in the pool") + @ManagedAttribute("number of configured reserved threads") public int getReservedThreads() { - if (isStarted()) + return _reservedThreads; + } + + @ManagedAttribute("maximum number of reserved threads") + public int getMaxReservedThreads() + { + TryExecutor tryExecutor = _tryExecutor; + if (tryExecutor instanceof ReservedThreadExecutor) { - ReservedThreadExecutor reservedThreadExecutor = getBean(ReservedThreadExecutor.class); - if (reservedThreadExecutor != null) - return reservedThreadExecutor.getCapacity(); + ReservedThreadExecutor reservedThreadExecutor = (ReservedThreadExecutor)tryExecutor; + return reservedThreadExecutor.getCapacity(); } - return _reservedThreads; + return 0; + } + + @ManagedAttribute("number of available reserved threads") + public int getAvailableReservedThreads() + { + TryExecutor tryExecutor = _tryExecutor; + if (tryExecutor instanceof ReservedThreadExecutor) + { + ReservedThreadExecutor reservedThreadExecutor = (ReservedThreadExecutor)tryExecutor; + return reservedThreadExecutor.getAvailable(); + } + return 0; } /** @@ -604,8 +621,26 @@ public int getIdleThreads() @ManagedAttribute("number of busy threads in the pool") public int getBusyThreads() { - int reserved = _tryExecutor instanceof ReservedThreadExecutor ? ((ReservedThreadExecutor)_tryExecutor).getAvailable() : 0; - return getThreads() - getIdleThreads() - reserved; + return getThreads() - getIdleThreads() - getAvailableReservedThreads(); + } + + @ManagedAttribute("number of potentially available threads in the pool") + public int getAvailableThreads() + { + return getMaxThreads() - getBusyThreads(); + } + + @ManagedAttribute("number of currently available threads in the pool") + public int getReadyThreads() + { + return getThreads() - getBusyThreads(); + } + + @ManagedAttribute("number of threads leased to components") + public int getLeasedThreads() + { + ThreadPoolBudget budget = _budget; + return budget == null ? 0 : budget.getLeasedThreads(); } /** diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPoolBudget.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPoolBudget.java index 22358196a674..39a3064213d0 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPoolBudget.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPoolBudget.java @@ -24,6 +24,8 @@ import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; +import org.eclipse.jetty.util.annotation.ManagedAttribute; +import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -32,9 +34,10 @@ * * @see ThreadPool.SizedThreadPool#getThreadPoolBudget() */ +@ManagedObject public class ThreadPoolBudget { - static final Logger LOG = Log.getLogger(ThreadPoolBudget.class); + private static final Logger LOG = Log.getLogger(ThreadPoolBudget.class); public interface Lease extends Closeable { @@ -115,6 +118,14 @@ public ThreadPool.SizedThreadPool getSizedThreadPool() return pool; } + @ManagedAttribute("the number of threads leased to components") + public int getLeasedThreads() + { + return leases.stream() + .mapToInt(Lease::getThreads) + .sum(); + } + public void reset() { leases.clear(); @@ -146,9 +157,7 @@ public Lease leaseTo(Object leasee, int threads) */ public boolean check(int maxThreads) throws IllegalStateException { - int required = leases.stream() - .mapToInt(Lease::getThreads) - .sum(); + int required = getLeasedThreads(); int left = maxThreads - required; if (left <= 0) {