Ok, this is not really an answer, more like an idea...
As I already mentioned in my earlier comment, your LoadingMessageSourceProvider
component maintains state, so someone must be responsible to properly shutdown the component. You could try to implement this as part of the component by registering a shutdown hook (I won't consider finalize
here :-).
I'd rather leave it to your components' user (application), as it better knows when to shutdown. In fact you're implementing a lightweight container having a lifecycle - in some way similar to a Java EE 7 container provider implementing JSR-236.
Given that you don't have a JSR-236 container available, you must enable the caller to manage lifecycle. I could think of a factory approach, simplified example:
// maintains the executor service (one service per factory)
private MessageSourceProviderFactory f = MessageSourceProviderFactory.instance();
private void stuff() {
MessageSourceProvider msp = f.newBuilder()/*. [...] */.build();
// work with the provider
}
// at some point in time the caller decides to finish
private void end() {
f.shutdown(); // shutdown the factory and the ExecutorService
}
JSR-236 section 3.1.6.1 is fairly interesting in terms of lifecycle:
3.1.6.1 Java EE Product Provider Requirements This subsection describes additional requirements for ManagedExecutorService
providers.
- All tasks, when executed from the ManagedExecutorService, will run with the Java EE component identity of the component that submitted
the task.
- The lifecycle of a ManagedExecutorService is managed by an application server. All lifecycle operations on the
ManagedExecutorService interface will throw a
java.lang.IllegalStateException exception. This includes the
following methods that are defined in the
java.util.concurrent.ExecutorService interface: awaitTermination(),
isShutdown(), isTerminated(), shutdown(), and shutdownNow().Final
Release 3-11
- No task submitted to an executor can run if task’s component is not started.
When a ManagedExecutorService instance is being shutdown by
the Java EE Product Provider:
- All attempts to submit new tasks are rejected.
- All submitted tasks are cancelled if not running.
- All running task threads are interrupted.
- All registered ManagedTaskListeners are invoked