Class BoundedExecutorService
- All Implemented Interfaces:
Executor, ExecutorService
ExecutorService wrapper that enforces bounded concurrency via a Semaphore.
When virtual threads are enabled, Camel replaces the traditional ThreadPoolExecutor with
Executors.newThreadPerTaskExecutor(), which accepts every task immediately (unbounded). This wrapper limits
the maximum number of tasks delegated to the underlying executor. Unlike ThreadPoolExecutor there is no
distinction between pool threads and queued tasks — the semaphore enforces a flat concurrency cap on delegated tasks.
When the semaphore has no available permits, behavior depends on the configured ThreadPoolRejectedPolicy:
- CallerRuns (default): blocks until a permit is available or the timeout expires; on timeout, runs the task
on the caller's thread. Tasks are never lost. Note that caller-run tasks execute outside semaphore accounting, so
total system concurrency may temporarily exceed
maxConcurrent. - Abort: blocks until a permit is available or the timeout expires; on timeout, throws
RejectedExecutionException. - Block: blocks indefinitely until a permit becomes available. No timeout, no rejection.
Caller thread blocking: while waiting for a permit, the calling thread is blocked. When callers are virtual threads this is inexpensive (the carrier thread is released). When callers are platform threads (e.g., HTTP server threads) the blocked thread is unavailable for other work — this is standard backpressure behavior but worth noting for capacity planning.
-
Constructor Summary
ConstructorsConstructorDescriptionBoundedExecutorService(ExecutorService delegate, int maxConcurrent, long acquireTimeout, TimeUnit timeUnit, boolean fair, ThreadPoolRejectedPolicy rejectedPolicy) -
Method Summary
Modifier and TypeMethodDescriptionbooleanawaitTermination(long timeout, TimeUnit unit) voidintThe number of tasks currently delegated to the underlying executor.intThe number of permits currently available.longThe number of times the timeout expired and a task fell back to running on the caller's thread.longThe total number of tasks that completed via the underlying executor (excludes caller-runs).intThe maximum number of tasks that can be delegated to the underlying executor concurrently.longThe number of tasks rejected because no permit was available within the timeout.intThe number of threads currently blocked waiting for a permit.booleanbooleanprotected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) voidshutdown()toString()
-
Constructor Details
-
BoundedExecutorService
public BoundedExecutorService(ExecutorService delegate, int maxConcurrent, long acquireTimeout, TimeUnit timeUnit, boolean fair, ThreadPoolRejectedPolicy rejectedPolicy) - Parameters:
delegate- the underlying executor (typicallynewThreadPerTaskExecutor)maxConcurrent- the maximum number of tasks delegated to the underlying executor concurrentlyacquireTimeout- the maximum time to wait for a permit (ignored when policy isBlock)timeUnit- the time unit foracquireTimeoutfair-truefor FIFO permit ordering (predictable latency),falsefor barging (higher throughput)rejectedPolicy- the policy to apply when no permit is available
-
-
Method Details
-
execute
-
getMaxConcurrent
The maximum number of tasks that can be delegated to the underlying executor concurrently. CallerRuns tasks execute outside this limit. -
getAvailablePermits
The number of permits currently available. -
getActiveCount
The number of tasks currently delegated to the underlying executor. -
getWaitingCount
The number of threads currently blocked waiting for a permit. -
getCallerRunsCount
The number of times the timeout expired and a task fell back to running on the caller's thread. -
getRejectedCount
The number of tasks rejected because no permit was available within the timeout. -
getDelegatedTaskCount
The total number of tasks that completed via the underlying executor (excludes caller-runs). -
newTaskFor
- Overrides:
newTaskForin classAbstractExecutorService
-
newTaskFor
- Overrides:
newTaskForin classAbstractExecutorService
-
shutdown
-
shutdownNow
-
isShutdown
-
isTerminated
-
awaitTermination
- Throws:
InterruptedException
-
toString
-