简体   繁体   中英

What are the best practices to manage an ExecutorService in a library?

In one of my libraries, I use a fixed thread pool executor with 5 threads; my threads are not heavyweight, I .get() with timeouts, but as to the ExecutorService , I create it and after that, this is "live and let die".

You are supposed to .shutdown{,Now}() it when you're done with it; but this being a library, I cannot know in advance how it will be used: with a simple main() , in a webapp which will be managed by the servlet container, others.

This doesn't feel right. How do I do better? Should I just be using something else than an ExecutorService ?

EDIT link to the only user: here ; daemon threads may be a solution, now I don't know if they have drawbacks I should be aware of...

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.

  1. All tasks, when executed from the ManagedExecutorService, will run with the Java EE component identity of the component that submitted the task.
  2. 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
  3. 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:

  1. All attempts to submit new tasks are rejected.
  2. All submitted tasks are cancelled if not running.
  3. All running task threads are interrupted.
  4. All registered ManagedTaskListeners are invoked

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM