Class BackgroundInitializer<T>
- java.lang.Object
-
- org.apache.commons.lang3.concurrent.AbstractConcurrentInitializer<T,java.lang.Exception>
-
- org.apache.commons.lang3.concurrent.BackgroundInitializer<T>
-
- Type Parameters:
T
- the type of the object managed by this initializer class
- All Implemented Interfaces:
ConcurrentInitializer<T>
,FailableSupplier<T,ConcurrentException>
- Direct Known Subclasses:
CallableBackgroundInitializer
,MultiBackgroundInitializer
public class BackgroundInitializer<T> extends AbstractConcurrentInitializer<T,java.lang.Exception>
A class that allows complex initialization operations in a background task.Applications often have to do some expensive initialization steps when they are started, e.g. constructing a connection to a database, reading a configuration file, etc. Doing these things in parallel can enhance performance as the CPU load can be improved. However, when access to the resources initialized in a background thread is actually required, synchronization has to be performed to ensure that their initialization is complete.
This abstract base class provides support for this use case. A concrete subclass must implement the
AbstractConcurrentInitializer.initialize()
method. Here an arbitrary initialization can be implemented, and a result object can be returned. With this method in place the basic usage of this class is as follows (whereMyBackgroundInitializer
is a concrete subclass):MyBackgroundInitializer initializer = new MyBackgroundInitializer(); initializer.start(); // Now do some other things. Initialization runs in a parallel thread ... // Wait for the end of initialization and access the result object Object result = initializer.get();
After the construction of a
BackgroundInitializer
object itsstart()
method has to be called. This starts the background processing. The application can now continue to do other things. When it needs access to the object produced by theBackgroundInitializer
it calls itsget()
method. If initialization is already complete,get()
returns the result object immediately. Otherwise it blocks until the result object is fully constructed.BackgroundInitializer
is a thin wrapper around aFuture
object and uses anExecutorService
for running the background initialization task. It is possible to pass in anExecutorService
at construction time or set one usingsetExternalExecutor()
beforestart()
was called. Then this object is used to spawn the background task. If noExecutorService
has been provided,BackgroundInitializer
creates a temporaryExecutorService
and destroys it when initialization is complete.The methods provided by
BackgroundInitializer
provide for minimal interaction with the wrappedFuture
object. It is also possible to obtain theFuture
object directly. Then the enhanced functionality offered byFuture
can be used, e.g. to check whether the background operation is complete or to cancel the operation.- Since:
- 3.0
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
BackgroundInitializer.Builder<I extends BackgroundInitializer<T>,T>
Builds a new instance.private class
BackgroundInitializer.InitializationTask
-
Nested classes/interfaces inherited from class org.apache.commons.lang3.concurrent.AbstractConcurrentInitializer
AbstractConcurrentInitializer.AbstractBuilder<I extends AbstractConcurrentInitializer<T,E>,T,B extends AbstractConcurrentInitializer.AbstractBuilder<I,T,B,E>,E extends java.lang.Exception>
-
-
Field Summary
Fields Modifier and Type Field Description private java.util.concurrent.ExecutorService
executor
A reference to the executor service that is actually used.private java.util.concurrent.ExecutorService
externalExecutor
The external executor service for executing tasks.private java.util.concurrent.Future<T>
future
Stores the handle to the background task.-
Fields inherited from interface org.apache.commons.lang3.function.FailableSupplier
NUL
-
-
Constructor Summary
Constructors Modifier Constructor Description protected
BackgroundInitializer()
Creates a new instance ofBackgroundInitializer
.protected
BackgroundInitializer(java.util.concurrent.ExecutorService exec)
Creates a new instance ofBackgroundInitializer
and initializes it with the givenExecutorService
.private
BackgroundInitializer(FailableSupplier<T,ConcurrentException> initializer, FailableConsumer<T,ConcurrentException> closer, java.util.concurrent.ExecutorService exec)
Constructs a new instance.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static <T> BackgroundInitializer.Builder<BackgroundInitializer<T>,T>
builder()
Creates a new builder.private java.util.concurrent.ExecutorService
createExecutor()
Creates theExecutorService
to be used.private java.util.concurrent.Callable<T>
createTask(java.util.concurrent.ExecutorService execDestroy)
Creates a task for the background initialization.T
get()
Returns the result of the background initialization.protected java.util.concurrent.ExecutorService
getActiveExecutor()
Returns theExecutorService
that is actually used for executing the background task.java.util.concurrent.ExecutorService
getExternalExecutor()
Returns the externalExecutorService
to be used by this class.java.util.concurrent.Future<T>
getFuture()
Returns theFuture
object that was created whenstart()
was called.protected int
getTaskCount()
Returns the number of background tasks to be created for this initializer.protected java.lang.Exception
getTypedException(java.lang.Exception e)
Gets an Exception with a type of E as defined by a concrete subclass of this class.boolean
isInitialized()
Tests whether this instance is initialized.boolean
isStarted()
Returns a flag whether thisBackgroundInitializer
has already been started.void
setExternalExecutor(java.util.concurrent.ExecutorService externalExecutor)
Sets anExecutorService
to be used by this class.boolean
start()
Starts the background initialization.-
Methods inherited from class org.apache.commons.lang3.concurrent.AbstractConcurrentInitializer
close, initialize
-
-
-
-
Field Detail
-
externalExecutor
private java.util.concurrent.ExecutorService externalExecutor
The external executor service for executing tasks.
-
executor
private java.util.concurrent.ExecutorService executor
A reference to the executor service that is actually used.
-
future
private java.util.concurrent.Future<T> future
Stores the handle to the background task.
-
-
Constructor Detail
-
BackgroundInitializer
protected BackgroundInitializer()
Creates a new instance ofBackgroundInitializer
. No externalExecutorService
is used.
-
BackgroundInitializer
protected BackgroundInitializer(java.util.concurrent.ExecutorService exec)
Creates a new instance ofBackgroundInitializer
and initializes it with the givenExecutorService
. If theExecutorService
is not null, the background task for initializing this object will be scheduled at this service. Otherwise a new temporaryExecutorService
is created.- Parameters:
exec
- an externalExecutorService
to be used for task execution
-
BackgroundInitializer
private BackgroundInitializer(FailableSupplier<T,ConcurrentException> initializer, FailableConsumer<T,ConcurrentException> closer, java.util.concurrent.ExecutorService exec)
Constructs a new instance.- Parameters:
initializer
- the initializer supplier called byAbstractConcurrentInitializer.initialize()
.closer
- the closer consumer called byAbstractConcurrentInitializer.close()
.exec
- theExecutorService
to be used @see #setExternalExecutor(ExecutorService)
-
-
Method Detail
-
builder
public static <T> BackgroundInitializer.Builder<BackgroundInitializer<T>,T> builder()
Creates a new builder.- Type Parameters:
T
- the type of object to build.- Returns:
- a new builder.
- Since:
- 3.14.0
-
createExecutor
private java.util.concurrent.ExecutorService createExecutor()
Creates theExecutorService
to be used. This method is called if noExecutorService
was provided at construction time.- Returns:
- the
ExecutorService
to be used
-
createTask
private java.util.concurrent.Callable<T> createTask(java.util.concurrent.ExecutorService execDestroy)
Creates a task for the background initialization. TheCallable
object returned by this method is passed to theExecutorService
. This implementation returns a task that invokes theAbstractConcurrentInitializer.initialize()
method. If a temporaryExecutorService
is used, it is destroyed at the end of the task.- Parameters:
execDestroy
- theExecutorService
to be destroyed by the task- Returns:
- a task for the background initialization
-
get
public T get() throws ConcurrentException
Returns the result of the background initialization. This method blocks until initialization is complete. If the background processing caused a runtime exception, it is directly thrown by this method. Checked exceptions, includingInterruptedException
are wrapped in aConcurrentException
. Calling this method beforestart()
was called causes anIllegalStateException
exception to be thrown.- Returns:
- the object produced by this initializer
- Throws:
ConcurrentException
- if a checked exception occurred during background processingjava.lang.IllegalStateException
- ifstart()
has not been called
-
getActiveExecutor
protected final java.util.concurrent.ExecutorService getActiveExecutor()
Returns theExecutorService
that is actually used for executing the background task. This method can be called afterstart()
(beforestart()
it returns null). If an external executor was set, this is also the active executor. Otherwise this method returns the temporary executor that was created by this object.- Returns:
- the
ExecutorService
for executing the background task
-
getExternalExecutor
public final java.util.concurrent.ExecutorService getExternalExecutor()
Returns the externalExecutorService
to be used by this class.- Returns:
- the
ExecutorService
-
getFuture
public java.util.concurrent.Future<T> getFuture()
Returns theFuture
object that was created whenstart()
was called. Therefore this method can only be called afterstart()
.- Returns:
- the
Future
object wrapped by this initializer - Throws:
java.lang.IllegalStateException
- ifstart()
has not been called
-
getTaskCount
protected int getTaskCount()
Returns the number of background tasks to be created for this initializer. This information is evaluated when a temporaryExecutorService
is created. This base implementation returns 1. Derived classes that do more complex background processing can override it. This method is called from a synchronized block by thestart()
method. Therefore overriding methods should be careful with obtaining other locks and return as fast as possible.- Returns:
- the number of background tasks required by this initializer
-
getTypedException
protected java.lang.Exception getTypedException(java.lang.Exception e)
Gets an Exception with a type of E as defined by a concrete subclass of this class.- Specified by:
getTypedException
in classAbstractConcurrentInitializer<T,java.lang.Exception>
- Parameters:
e
- The actual exception that was thrown- Returns:
- a new exception with the actual type of E, that wraps e.
-
isInitialized
public boolean isInitialized()
Tests whether this instance is initialized. Once initialized, always returns true. If initialization failed then the failure will be cached and this will never return true.- Specified by:
isInitialized
in classAbstractConcurrentInitializer<T,java.lang.Exception>
- Returns:
- true if initialization completed successfully, otherwise false
- Since:
- 3.14.0
-
isStarted
public boolean isStarted()
Returns a flag whether thisBackgroundInitializer
has already been started.- Returns:
- a flag whether the
start()
method has already been called
-
setExternalExecutor
public final void setExternalExecutor(java.util.concurrent.ExecutorService externalExecutor)
Sets anExecutorService
to be used by this class. TheExecutorService
passed to this method is used for executing the background task. Thus it is possible to re-use an already existingExecutorService
or to use a specially configured one. If noExecutorService
is set, this instance creates a temporary one and destroys it after background initialization is complete. Note that this method must be called beforestart()
; otherwise an exception is thrown.- Parameters:
externalExecutor
- theExecutorService
to be used- Throws:
java.lang.IllegalStateException
- if this initializer has already been started
-
start
public boolean start()
Starts the background initialization. With this method the initializer becomes active and invokes theAbstractConcurrentInitializer.initialize()
method in a background task. ABackgroundInitializer
can be started exactly once. The return value of this method determines whether the start was successful: only the first invocation of this method returns true, following invocations will return false.- Returns:
- a flag whether the initializer could be started successfully
-
-