Class ContextTrackingExecutor
- java.lang.Object
-
- pl.morgwai.base.guice.scopes.ContextTrackingExecutor
-
- All Implemented Interfaces:
Executor
public class ContextTrackingExecutor extends Object implements Executor
An executor that automatically updates which thread runs within whichTrackableContext
when executing a task. By default backed by a fixed sizeThreadPoolExecutor
.Instances usually correspond 1-1 with some type of blocking or time consuming operations, such as CPU intensive calculations or blocking network communication with some resource.
In case of network operations, a given threadPool size should usually correspond to the pool size of the connections to the given resource.
In case of CPU intensive operations, it should usually correspond to the number of cores available to the process (Runtime.availableProcessors()
).Instances are usually created at app startup, stored on static vars and/or bound for injection with a specific
name
:bind(ContextTrackingExecutor.class) .annotatedWith(Names.named("someOpTypeExecutor")) .toInstance(...)
and then injected using @
Named
annotation:@Named("someOpTypeExecutor") ContextTrackingExecutor someOpTypeExecutor
At app shutdown
shutdown()
should be called followed by eitherenforceTermination(long, TimeUnit)
orawaitTermination()
orawaitTermination(long, TimeUnit)
andshutdownNow()
in case of a failure.If multiple threads run within the same context, then the attributes they access must be thread-safe or properly synchronized.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
ContextTrackingExecutor.NamedThreadFactory
A thread factory that names new threads based on its own name.
-
Field Summary
Fields Modifier and Type Field Description protected static org.slf4j.Logger
log
-
Constructor Summary
Constructors Constructor Description ContextTrackingExecutor(String name, int poolSize, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, List<ContextTracker<?>> trackers)
Constructs an instance backed by a new fixed sizeThreadPoolExecutor
.ContextTrackingExecutor(String name, int poolSize, BlockingQueue<Runnable> workQueue, List<ContextTracker<?>> trackers)
Constructs an instance backed by a new fixed sizeThreadPoolExecutor
that uses aNamedThreadFactory
.ContextTrackingExecutor(String name, int poolSize, List<ContextTracker<?>> trackers)
Constructs an instance backed by a new fixed sizeThreadPoolExecutor
that uses aNamedThreadFactory
and an unboundLinkedBlockingQueue
.ContextTrackingExecutor(String name, ExecutorService backingExecutor, int poolSize, List<ContextTracker<?>> trackers)
Constructs an instance backed bybackingExecutor
.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
awaitTermination()
Keeps callingbackingExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)
until it returnstrue
.boolean
awaitTermination(long timeout, TimeUnit unit)
Optional<List<Runnable>>
enforceTermination(long timeout, TimeUnit unit)
Awaits
up totimeoutMillis
for termination and if executor fails to do so either due to timeout or interruptshutdownNow()
is called.
Logs outcome toLogger
named after this class.void
execute(Runnable task)
Executestask
within all contexts that were active when this method was called.<T> CompletableFuture<T>
execute(Callable<T> task)
Convenience method to execute aCallable
.static void
executeWithinAll(List<TrackableContext<?>> contexts, Runnable operation)
Executesoperation
on the current thread within allcontexts
.static <T> T
executeWithinAll(List<TrackableContext<?>> contexts, Callable<T> operation)
Executesoperation
on the current thread within allcontexts
.static List<TrackableContext<?>>
getActiveContexts(List<ContextTracker<?>> trackers)
Retrieves all active contexts fromtrackers
.String
getName()
int
getPoolSize()
boolean
isShutdown()
CallsbackingExecutor.isShutdown()
.boolean
isTerminated()
void
shutdown()
CallsbackingExecutor.shutdown()
.List<Runnable>
shutdownNow()
String
toString()
-
-
-
Constructor Detail
-
ContextTrackingExecutor
public ContextTrackingExecutor(String name, int poolSize, List<ContextTracker<?>> trackers)
Constructs an instance backed by a new fixed sizeThreadPoolExecutor
that uses aNamedThreadFactory
and an unboundLinkedBlockingQueue
.To avoid
OutOfMemoryError
s, an external mechanism that limits maximum number of tasks (such as a load balancer or a frontend proxy) should be used.
-
ContextTrackingExecutor
public ContextTrackingExecutor(String name, int poolSize, BlockingQueue<Runnable> workQueue, List<ContextTracker<?>> trackers)
Constructs an instance backed by a new fixed sizeThreadPoolExecutor
that uses aNamedThreadFactory
.execute(Runnable)
throws aRejectedExecutionException
ifworkQueue
is full. It should usually be handled by informing the client that the service has temporarily exceeded its capacity (for example a gRPC can send statusUNAVAILABLE(14)
and a servlet can send status503 Service Unavailable
).
-
ContextTrackingExecutor
public ContextTrackingExecutor(String name, int poolSize, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, List<ContextTracker<?>> trackers)
Constructs an instance backed by a new fixed sizeThreadPoolExecutor
.execute(Runnable)
throws aRejectedExecutionException
ifworkQueue
is full. It should usually be handled by informing the client that the service has temporarily exceeded its capacity (for example a gRPC can send statusUNAVAILABLE(14)
and a servlet can send status503 Service Unavailable
).
-
ContextTrackingExecutor
public ContextTrackingExecutor(String name, ExecutorService backingExecutor, int poolSize, List<ContextTracker<?>> trackers)
Constructs an instance backed bybackingExecutor
.- Parameters:
poolSize
- informative only: to be returned bygetPoolSize()
.
-
-
Method Detail
-
getPoolSize
public int getPoolSize()
-
getName
public String getName()
-
execute
public <T> CompletableFuture<T> execute(Callable<T> task)
Convenience method to execute aCallable
.- See Also:
execute(Runnable)
-
execute
public void execute(Runnable task)
Executestask
within all contexts that were active when this method was called.
-
getActiveContexts
public static List<TrackableContext<?>> getActiveContexts(List<ContextTracker<?>> trackers)
Retrieves all active contexts fromtrackers
. The returned list can be then used as an argument toexecuteWithinAll(List, Runnable)
to transfer the contexts after a switch to another thread.Libraries usually bind
List<ContextTracker<?>>
to an instance containing all possible trackers for use as an argument for this method.
-
executeWithinAll
public static void executeWithinAll(List<TrackableContext<?>> contexts, Runnable operation)
Executesoperation
on the current thread within allcontexts
. Used to transfer active contexts after a switch to another thread.- See Also:
getActiveContexts(List)
-
executeWithinAll
public static <T> T executeWithinAll(List<TrackableContext<?>> contexts, Callable<T> operation) throws Exception
Executesoperation
on the current thread within allcontexts
. Used to transfer active contexts after a switch to another thread.- Throws:
Exception
- See Also:
getActiveContexts(List)
-
shutdown
public void shutdown()
CallsbackingExecutor.shutdown()
.
-
isShutdown
public boolean isShutdown()
CallsbackingExecutor.isShutdown()
.
-
isTerminated
public boolean isTerminated()
-
enforceTermination
public Optional<List<Runnable>> enforceTermination(long timeout, TimeUnit unit) throws InterruptedException
Awaits
up totimeoutMillis
for termination and if executor fails to do so either due to timeout or interruptshutdownNow()
is called.
Logs outcome toLogger
named after this class.Should be called at app shutdown.
- Returns:
empty
if the executor was shutdown cleanly, list of tasks returned bybackingExecutor.shutdownNow()
otherwise.- Throws:
InterruptedException
- See Also:
ExecutorService.awaitTermination(long, TimeUnit)
,ExecutorService.shutdownNow()
-
awaitTermination
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
- Throws:
InterruptedException
- See Also:
enforceTermination(long, TimeUnit)
-
awaitTermination
public void awaitTermination() throws InterruptedException
Keeps callingbackingExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)
until it returnstrue
.
-
shutdownNow
public List<Runnable> shutdownNow()
- See Also:
enforceTermination(long, TimeUnit)
-
-